* Hooks may return void or may return a boolean. If the method returns
@@ -665,7 +665,7 @@ public enum Pointcut {
* returns false, processing will be aborted.
*
*/
- SUBSCRIPTION_BEFORE_DELIVERY(boolean.class, "ca.uhn.fhir.jpa.subscription.module.CanonicalSubscription", "ca.uhn.fhir.jpa.subscription.module.subscriber.ResourceDeliveryMessage"),
+ SUBSCRIPTION_BEFORE_DELIVERY(boolean.class, "ca.uhn.fhir.jpa.subscription.model.CanonicalSubscription", "ca.uhn.fhir.jpa.subscription.model.ResourceDeliveryMessage"),
/**
* Subscription Hook:
@@ -675,14 +675,14 @@ public enum Pointcut {
* Hooks may accept the following parameters:
*
*
java.lang.Exception - The exception that caused the failure. Note this could be an exception thrown by a SUBSCRIPTION_BEFORE_DELIVERY or SUBSCRIPTION_AFTER_DELIVERY interceptor
- *
ca.uhn.fhir.jpa.subscription.module.subscriber.ResourceDeliveryMessage - the message that triggered the exception
+ *
ca.uhn.fhir.jpa.subscription.model.ResourceDeliveryMessage - the message that triggered the exception
*
java.lang.Exception
*
*
@@ -706,7 +706,7 @@ public enum Pointcut {
* taken for the delivery.
*
*/
- SUBSCRIPTION_AFTER_DELIVERY_FAILED(boolean.class, "ca.uhn.fhir.jpa.subscription.module.subscriber.ResourceDeliveryMessage", "java.lang.Exception"),
+ SUBSCRIPTION_AFTER_DELIVERY_FAILED(boolean.class, "ca.uhn.fhir.jpa.subscription.model.ResourceDeliveryMessage", "java.lang.Exception"),
/**
* Subscription Hook:
@@ -717,14 +717,14 @@ public enum Pointcut {
*
* Hooks may accept the following parameters:
*
* Hooks may return void or may return a boolean. If the method returns
@@ -745,7 +745,7 @@ public enum Pointcut {
* returns false, processing will be aborted.
*
ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage - This parameter should not be modified as processing is complete when this hook is invoked.
+ *
ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage - This parameter should not be modified as processing is complete when this hook is invoked.
*
*
*
* Hooks should return void.
*
*/
- SUBSCRIPTION_AFTER_PERSISTED_RESOURCE_CHECKED(void.class, "ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage"),
+ SUBSCRIPTION_AFTER_PERSISTED_RESOURCE_CHECKED(void.class, "ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage"),
/**
@@ -796,13 +796,13 @@ public enum Pointcut {
*
* Hooks may accept the following parameters:
*
- This is the home for the FHIR test server operated by
- University Health Network. This server
- (and the testing application you are currently using to access it)
- is entirely built using
- HAPI-FHIR,
- a 100% open-source Java implementation of the
- FHIR specification.
-
- Access a
- different server
- (use the Server menu at the top of the page to see a list of public FHIR servers)
-
-
-
-
-
- You are accessing the public FHIR server
- . This server is hosted elsewhere on the internet
- but is being accessed using the HAPI client implementation.
-
-
-
-
-
- This is not a production server!
-
- Do not store any information here that contains personal health information
- or any other confidential information. This server will be regularly purged
- and reloaded with fixed test data.
-
-
-
diff --git a/hapi-fhir-jpaserver-example/src/main/webapp/WEB-INF/web-dstu2.xml b/hapi-fhir-jpaserver-example/src/main/webapp/WEB-INF/web-dstu2.xml
deleted file mode 100644
index de1a573d1c4..00000000000
--- a/hapi-fhir-jpaserver-example/src/main/webapp/WEB-INF/web-dstu2.xml
+++ /dev/null
@@ -1,106 +0,0 @@
-
-
-
- org.springframework.web.context.ContextLoaderListener
-
-
- contextClass
-
- org.springframework.web.context.support.AnnotationConfigWebApplicationContext
-
-
-
- contextConfigLocation
-
- ca.uhn.fhir.jpa.demo.FhirServerConfigDstu2
-
-
-
-
-
-
- spring
- org.springframework.web.servlet.DispatcherServlet
-
- contextClass
- org.springframework.web.context.support.AnnotationConfigWebApplicationContext
-
-
- contextConfigLocation
- ca.uhn.fhir.jpa.demo.FhirTesterConfigDstu2
-
- 2
-
-
-
- fhirServlet
- ca.uhn.fhir.jpa.demo.JpaServerDemoDstu2
-
- ImplementationDescription
- FHIR JPA Server
-
-
- FhirVersion
- DSTU2
-
- 1
-
-
-
- fhirServlet
- /baseDstu2/*
-
-
-
- spring
- /
-
-
-
-
-
-
- CORS Filter
- org.ebaysf.web.cors.CORSFilter
-
- A comma separated list of allowed origins. Note: An '*' cannot be used for an allowed origin when using credentials.
- cors.allowed.origins
- *
-
-
- A comma separated list of HTTP verbs, using which a CORS request can be made.
- cors.allowed.methods
- GET,POST,PUT,DELETE,OPTIONS
-
-
- A comma separated list of allowed headers when making a non simple CORS request.
- cors.allowed.headers
- X-FHIR-Starter,Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers
-
-
- A comma separated list non-standard response headers that will be exposed to XHR2 object.
- cors.exposed.headers
- Location,Content-Location
-
-
- A flag that suggests if CORS is supported with cookies
- cors.support.credentials
- true
-
-
- A flag to control logging
- cors.logging.enabled
- true
-
-
- Indicates how long (in seconds) the results of a preflight request can be cached in a preflight result cache.
- cors.preflight.maxage
- 300
-
-
-
- CORS Filter
- /*
-
-
diff --git a/hapi-fhir-jpaserver-example/src/main/webapp/WEB-INF/web.xml b/hapi-fhir-jpaserver-example/src/main/webapp/WEB-INF/web.xml
deleted file mode 100644
index a09387d37ea..00000000000
--- a/hapi-fhir-jpaserver-example/src/main/webapp/WEB-INF/web.xml
+++ /dev/null
@@ -1,108 +0,0 @@
-
-
-
- org.springframework.web.context.ContextLoaderListener
-
-
- contextClass
-
- org.springframework.web.context.support.AnnotationConfigWebApplicationContext
-
-
-
- contextConfigLocation
-
- ca.uhn.fhir.jpa.demo.FhirServerConfig
-
-
-
-
-
-
- spring
- org.springframework.web.servlet.DispatcherServlet
-
- contextClass
- org.springframework.web.context.support.AnnotationConfigWebApplicationContext
-
-
- contextConfigLocation
- ca.uhn.fhir.jpa.demo.FhirTesterConfig
-
- 2
-
-
-
- fhirServlet
- ca.uhn.fhir.jpa.demo.JpaServerDemo
-
- ImplementationDescription
- FHIR JPA Server
-
-
- FhirVersion
- DSTU3
-
- 1
-
-
-
- fhirServlet
- /baseDstu3/*
-
-
-
- spring
- /
-
-
-
-
-
-
- CORS Filter
- org.ebaysf.web.cors.CORSFilter
-
- A comma separated list of allowed origins. Note: An '*' cannot be used for an allowed origin when using credentials.
- cors.allowed.origins
- *
-
-
- A comma separated list of HTTP verbs, using which a CORS request can be made.
- cors.allowed.methods
- GET,POST,PUT,DELETE,OPTIONS
-
-
- A comma separated list of allowed headers when making a non simple CORS request.
- cors.allowed.headers
- Accept,Access-Control-Request-Headers,Access-Control-Request-Method,Cache-Control,Content-Type,Origin,Prefer,X-FHIR-Starter,X-Requested-With
-
-
- A comma separated list non-standard response headers that will be exposed to XHR2 object.
- cors.exposed.headers
- Location,Content-Location
-
-
- A flag that suggests if CORS is supported with cookies
- cors.support.credentials
- true
-
-
- A flag to control logging
- cors.logging.enabled
- true
-
-
- Indicates how long (in seconds) the results of a preflight request can be cached in a preflight result cache.
- cors.preflight.maxage
- 300
-
-
-
- CORS Filter
- /*
-
-
-
-
diff --git a/hapi-fhir-jpaserver-example/src/main/webapp/WEB-INF/xsd/javaee_6.xsd b/hapi-fhir-jpaserver-example/src/main/webapp/WEB-INF/xsd/javaee_6.xsd
deleted file mode 100644
index 9fb587749ce..00000000000
--- a/hapi-fhir-jpaserver-example/src/main/webapp/WEB-INF/xsd/javaee_6.xsd
+++ /dev/null
@@ -1,2419 +0,0 @@
-
-
-
-
-
- DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
-
- Copyright 2003-2009 Sun Microsystems, Inc. All rights reserved.
-
- The contents of this file are subject to the terms of either the
- GNU General Public License Version 2 only ("GPL") or the Common
- Development and Distribution License("CDDL") (collectively, the
- "License"). You may not use this file except in compliance with
- the License. You can obtain a copy of the License at
- https://glassfish.dev.java.net/public/CDDL+GPL.html or
- glassfish/bootstrap/legal/LICENSE.txt. See the License for the
- specific language governing permissions and limitations under the
- License.
-
- When distributing the software, include this License Header
- Notice in each file and include the License file at
- glassfish/bootstrap/legal/LICENSE.txt. Sun designates this
- particular file as subject to the "Classpath" exception as
- provided by Sun in the GPL Version 2 section of the License file
- that accompanied this code. If applicable, add the following
- below the License Header, with the fields enclosed by brackets []
- replaced by your own identifying information:
- "Portions Copyrighted [year] [name of copyright owner]"
-
- Contributor(s):
-
- If you wish your version of this file to be governed by only the
- CDDL or only the GPL Version 2, indicate your decision by adding
- "[Contributor] elects to include this software in this
- distribution under the [CDDL or GPL Version 2] license." If you
- don't indicate a single choice of license, a recipient has the
- option to distribute your version of this file under either the
- CDDL, the GPL Version 2 or to extend the choice of license to its
- licensees as provided above. However, if you add GPL Version 2
- code and therefore, elected the GPL Version 2 license, then the
- option applies only if the new code is made subject to such
- option by the copyright holder.
-
-
-
-
-
-
-
- The following definitions that appear in the common
- shareable schema(s) of Java EE deployment descriptors should be
- interpreted with respect to the context they are included:
-
- Deployment Component may indicate one of the following:
- java ee application;
- application client;
- web application;
- enterprise bean;
- resource adapter;
-
- Deployment File may indicate one of the following:
- ear file;
- war file;
- jar file;
- rar file;
-
-
-
-
-
-
-
-
-
-
- This group keeps the usage of the contained description related
- elements consistent across Java EE deployment descriptors.
-
- All elements may occur multiple times with different languages,
- to support localization of the content.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This group keeps the usage of the contained JNDI environment
- reference elements consistent across Java EE deployment descriptors.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This group collects elements that are common to most
- JNDI resource elements.
-
-
-
-
-
-
-
-
-
- The JNDI name to be looked up to resolve a resource reference.
-
-
-
-
-
-
-
-
-
-
-
- This group collects elements that are common to all the
- JNDI resource elements. It does not include the lookup-name
- element, that is only applicable to some resource elements.
-
-
-
-
-
-
-
-
- A product specific name that this resource should be
- mapped to. The name of this resource, as defined by the
- resource's name element or defaulted, is a name that is
- local to the application component using the resource.
- (It's a name in the JNDI java:comp/env namespace.) Many
- application servers provide a way to map these local
- names to names of resources known to the application
- server. This mapped name is often a global JNDI name,
- but may be a name of any form.
-
- Application servers are not required to support any
- particular form or type of mapped name, nor the ability
- to use mapped names. The mapped name is
- product-dependent and often installation-dependent. No
- use of a mapped name is portable.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Configuration of a DataSource.
-
-
-
-
-
-
-
-
- Description of this DataSource.
-
-
-
-
-
-
-
-
- The name element specifies the JNDI name of the
- data source being defined.
-
-
-
-
-
-
-
-
- DataSource, XADataSource or ConnectionPoolDataSource
- implementation class.
-
-
-
-
-
-
-
-
- Database server name.
-
-
-
-
-
-
-
-
- Port number where a server is listening for requests.
-
-
-
-
-
-
-
-
- Name of a database on a server.
-
-
-
-
-
-
-
- url property is specified
- along with other standard DataSource properties
- such as serverName, databaseName
- and portNumber, the more specific properties will
- take precedence and url will be ignored.
-
- ]]>
-
-
-
-
-
-
-
- User name to use for connection authentication.
-
-
-
-
-
-
-
-
- Password to use for connection authentication.
-
-
-
-
-
-
-
-
- JDBC DataSource property. This may be a vendor-specific
- property or a less commonly used DataSource property.
-
-
-
-
-
-
-
-
- Sets the maximum time in seconds that this data source
- will wait while attempting to connect to a database.
-
-
-
-
-
-
-
-
- Set to false if connections should not participate in
- transactions.
-
-
-
-
-
-
-
-
- Isolation level for connections.
-
-
-
-
-
-
-
-
- Number of connections that should be created when a
- connection pool is initialized.
-
-
-
-
-
-
-
-
- Maximum number of connections that should be concurrently
- allocated for a connection pool.
-
-
-
-
-
-
-
-
- Minimum number of connections that should be concurrently
- allocated for a connection pool.
-
-
-
-
-
-
-
-
- The number of seconds that a physical connection should
- remain unused in the pool before the connection is
- closed for a connection pool.
-
-
-
-
-
-
-
-
- The total number of statements that a connection pool
- should keep open.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The description type is used by a description element to
- provide text describing the parent element. The elements
- that use this type should include any information that the
- Deployment Component's Deployment File file producer wants
- to provide to the consumer of the Deployment Component's
- Deployment File (i.e., to the Deployer). Typically, the
- tools used by such a Deployment File consumer will display
- the description when processing the parent element that
- contains the description.
-
- The lang attribute defines the language that the
- description is provided in. The default value is "en" (English).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This type defines a dewey decimal that is used
- to describe versions of documents.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Employee Self Service
-
-
- The value of the xml:lang attribute is "en" (English) by default.
-
- ]]>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- EmployeeRecord
-
- ../products/product.jar#ProductEJB
-
- ]]>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The ejb-local-refType is used by ejb-local-ref elements for
- the declaration of a reference to an enterprise bean's local
- home or to the local business interface of a 3.0 bean.
- The declaration consists of:
-
- - an optional description
- - the EJB reference name used in the code of the Deployment
- Component that's referencing the enterprise bean.
- - the optional expected type of the referenced enterprise bean
- - the optional expected local interface of the referenced
- enterprise bean or the local business interface of the
- referenced enterprise bean.
- - the optional expected local home interface of the referenced
- enterprise bean. Not applicable if this ejb-local-ref refers
- to the local business interface of a 3.0 bean.
- - optional ejb-link information, used to specify the
- referenced enterprise bean
- - optional elements to define injection of the named enterprise
- bean into a component field or property.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ejb/Payroll
-
- ]]>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The ejb-refType is used by ejb-ref elements for the
- declaration of a reference to an enterprise bean's home or
- to the remote business interface of a 3.0 bean.
- The declaration consists of:
-
- - an optional description
- - the EJB reference name used in the code of
- the Deployment Component that's referencing the enterprise
- bean.
- - the optional expected type of the referenced enterprise bean
- - the optional remote interface of the referenced enterprise bean
- or the remote business interface of the referenced enterprise
- bean
- - the optional expected home interface of the referenced
- enterprise bean. Not applicable if this ejb-ref
- refers to the remote business interface of a 3.0 bean.
- - optional ejb-link information, used to specify the
- referenced enterprise bean
- - optional elements to define injection of the named enterprise
- bean into a component field or property
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The ejb-ref-typeType contains the expected type of the
- referenced enterprise bean.
-
- The ejb-ref-type designates a value
- that must be one of the following:
-
- Entity
- Session
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This type is used to designate an empty
- element when used.
-
-
-
-
-
-
-
-
-
-
-
-
-
- The env-entryType is used to declare an application's
- environment entry. The declaration consists of an optional
- description, the name of the environment entry, a type
- (optional if the value is injected, otherwise required), and
- an optional value.
-
- It also includes optional elements to define injection of
- the named resource into fields or JavaBeans properties.
-
- If a value is not specified and injection is requested,
- no injection will occur and no entry of the specified name
- will be created. This allows an initial value to be
- specified in the source code without being incorrectly
- changed when no override has been specified.
-
- If a value is not specified and no injection is requested,
- a value must be supplied during deployment.
-
- This type is used by env-entry elements.
-
-
-
-
-
-
-
-
- minAmount
-
- ]]>
-
-
-
-
-
-
- java.lang.Integer
-
- ]]>
-
-
-
-
-
-
- 100.00
-
- ]]>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- java.lang.Boolean
- java.lang.Class
- com.example.Color
-
- ]]>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The elements that use this type designate the name of a
- Java class or interface. The name is in the form of a
- "binary name", as defined in the JLS. This is the form
- of name used in Class.forName(). Tools that need the
- canonical name (the name used in source code) will need
- to convert this binary name to the canonical name.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This type defines four different values which can designate
- boolean values. This includes values yes and no which are
- not designated by xsd:boolean
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The icon type contains small-icon and large-icon elements
- that specify the file names for small and large GIF, JPEG,
- or PNG icon images used to represent the parent element in a
- GUI tool.
-
- The xml:lang attribute defines the language that the
- icon file names are provided in. Its value is "en" (English)
- by default.
-
-
-
-
-
-
-
- employee-service-icon16x16.jpg
-
- ]]>
-
-
-
-
-
-
- employee-service-icon32x32.jpg
-
- ]]>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- An injection target specifies a class and a name within
- that class into which a resource should be injected.
-
- The injection target class specifies the fully qualified
- class name that is the target of the injection. The
- Java EE specifications describe which classes can be an
- injection target.
-
- The injection target name specifies the target within
- the specified class. The target is first looked for as a
- JavaBeans property name. If not found, the target is
- looked for as a field name.
-
- The specified resource will be injected into the target
- during initialization of the class by either calling the
- set method for the target property or by setting a value
- into the named field.
-
-
-
-
-
-
-
-
-
-
-
-
-
- The following transaction isolation levels are allowed
- (see documentation for the java.sql.Connection interface):
- TRANSACTION_READ_UNCOMMITTED
- TRANSACTION_READ_COMMITTED
- TRANSACTION_REPEATABLE_READ
- TRANSACTION_SERIALIZABLE
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The java-identifierType defines a Java identifier.
- The users of this type should further verify that
- the content does not contain Java reserved keywords.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This is a generic type that designates a Java primitive
- type or a fully qualified name of a Java interface/type,
- or an array of such types.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- :
-
- Example:
-
- jdbc:mysql://localhost:3307/testdb
-
- ]]>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The jndi-nameType type designates a JNDI name in the
- Deployment Component's environment and is relative to the
- java:comp/env context. A JNDI name must be unique within the
- Deployment Component.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- com.aardvark.payroll.PayrollHome
-
- ]]>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The lifecycle-callback type specifies a method on a
- class to be called when a lifecycle event occurs.
- Note that each class may have only one lifecycle callback
- method for any given event and that the method may not
- be overloaded.
-
- If the lifefycle-callback-class element is missing then
- the class defining the callback is assumed to be the
- component class in scope at the place in the descriptor
- in which the callback definition appears.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The listenerType indicates the deployment properties for a web
- application listener bean.
-
-
-
-
-
-
-
-
-
- The listener-class element declares a class in the
- application must be registered as a web
- application listener bean. The value is the fully
- qualified classname of the listener class.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The localType defines the fully-qualified name of an
- enterprise bean's local interface.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The local-homeType defines the fully-qualified
- name of an enterprise bean's local home interface.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This type is a general type that can be used to declare
- parameter/value lists.
-
-
-
-
-
-
-
-
-
- The param-name element contains the name of a
- parameter.
-
-
-
-
-
-
-
-
- The param-value element contains the value of a
- parameter.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The elements that use this type designate either a relative
- path or an absolute path starting with a "/".
-
- In elements that specify a pathname to a file within the
- same Deployment File, relative filenames (i.e., those not
- starting with "/") are considered relative to the root of
- the Deployment File's namespace. Absolute filenames (i.e.,
- those starting with "/") also specify names in the root of
- the Deployment File's namespace. In general, relative names
- are preferred. The exception is .war files where absolute
- names are preferred for consistency with the Servlet API.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- myPersistenceContext
-
-
-
-
- myPersistenceContext
-
- PersistenceUnit1
-
- Extended
-
-
- ]]>
-
-
-
-
-
-
-
-
- The persistence-context-ref-name element specifies
- the name of a persistence context reference; its
- value is the environment entry name used in
- Deployment Component code. The name is a JNDI name
- relative to the java:comp/env context.
-
-
-
-
-
-
-
-
- The Application Assembler(or BeanProvider) may use the
- following syntax to avoid the need to rename persistence
- units to have unique names within a Java EE application.
-
- The Application Assembler specifies the pathname of the
- root of the persistence.xml file for the referenced
- persistence unit and appends the name of the persistence
- unit separated from the pathname by #. The pathname is
- relative to the referencing application component jar file.
- In this manner, multiple persistence units with the same
- persistence unit name may be uniquely identified when the
- Application Assembler cannot change persistence unit names.
-
-
-
-
-
-
-
-
-
- Used to specify properties for the container or persistence
- provider. Vendor-specific properties may be included in
- the set of properties. Properties that are not recognized
- by a vendor must be ignored. Entries that make use of the
- namespace javax.persistence and its subnamespaces must not
- be used for vendor-specific properties. The namespace
- javax.persistence is reserved for use by the specification.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The persistence-context-typeType specifies the transactional
- nature of a persistence context reference.
-
- The value of the persistence-context-type element must be
- one of the following:
- Transaction
- Extended
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Specifies a name/value pair.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- myPersistenceUnit
-
-
-
-
- myPersistenceUnit
-
- PersistenceUnit1
-
-
-
- ]]>
-
-
-
-
-
-
-
-
- The persistence-unit-ref-name element specifies
- the name of a persistence unit reference; its
- value is the environment entry name used in
- Deployment Component code. The name is a JNDI name
- relative to the java:comp/env context.
-
-
-
-
-
-
-
-
- The Application Assembler(or BeanProvider) may use the
- following syntax to avoid the need to rename persistence
- units to have unique names within a Java EE application.
-
- The Application Assembler specifies the pathname of the
- root of the persistence.xml file for the referenced
- persistence unit and appends the name of the persistence
- unit separated from the pathname by #. The pathname is
- relative to the referencing application component jar file.
- In this manner, multiple persistence units with the same
- persistence unit name may be uniquely identified when the
- Application Assembler cannot change persistence unit names.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- com.wombat.empl.EmployeeService
-
- ]]>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- jms/StockQueue
-
- javax.jms.Queue
-
-
-
- ]]>
-
-
-
-
-
-
-
-
- The resource-env-ref-name element specifies the name
- of a resource environment reference; its value is
- the environment entry name used in
- the Deployment Component code. The name is a JNDI
- name relative to the java:comp/env context and must
- be unique within a Deployment Component.
-
-
-
-
-
-
-
-
- The resource-env-ref-type element specifies the type
- of a resource environment reference. It is the
- fully qualified name of a Java language class or
- interface.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- jdbc/EmployeeAppDB
- javax.sql.DataSource
- Container
- Shareable
-
-
- ]]>
-
-
-
-
-
-
-
-
- The res-ref-name element specifies the name of a
- resource manager connection factory reference.
- The name is a JNDI name relative to the
- java:comp/env context.
- The name must be unique within a Deployment File.
-
-
-
-
-
-
-
-
- The res-type element specifies the type of the data
- source. The type is specified by the fully qualified
- Java language class or interface
- expected to be implemented by the data source.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The res-authType specifies whether the Deployment Component
- code signs on programmatically to the resource manager, or
- whether the Container will sign on to the resource manager
- on behalf of the Deployment Component. In the latter case,
- the Container uses information that is supplied by the
- Deployer.
-
- The value must be one of the two following:
-
- Application
- Container
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The res-sharing-scope type specifies whether connections
- obtained through the given resource manager connection
- factory reference can be shared. The value, if specified,
- must be one of the two following:
-
- Shareable
- Unshareable
-
- The default value is Shareable.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The run-asType specifies the run-as identity to be
- used for the execution of a component. It contains an
- optional description, and the name of a security role.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The role-nameType designates the name of a security role.
-
- The name must conform to the lexical rules for a token.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This role includes all employees who are authorized
- to access the employee service application.
-
- employee
-
-
- ]]>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The security-role-refType contains the declaration of a
- security role reference in a component's or a
- Deployment Component's code. The declaration consists of an
- optional description, the security role name used in the
- code, and an optional link to a security role. If the
- security role is not specified, the Deployer must choose an
- appropriate security role.
-
-
-
-
-
-
-
-
-
- The value of the role-name element must be the String used
- as the parameter to the
- EJBContext.isCallerInRole(String roleName) method or the
- HttpServletRequest.isUserInRole(String role) method.
-
-
-
-
-
-
-
-
- The role-link element is a reference to a defined
- security role. The role-link element must contain
- the name of one of the security roles defined in the
- security-role elements.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This type adds an "id" attribute to xsd:QName.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This type adds an "id" attribute to xsd:boolean.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This type adds an "id" attribute to xsd:NMTOKEN.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This type adds an "id" attribute to xsd:anyURI.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This type adds an "id" attribute to xsd:integer.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This type adds an "id" attribute to xsd:positiveInteger.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This type adds an "id" attribute to xsd:nonNegativeInteger.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This type adds an "id" attribute to xsd:string.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This is a special string datatype that is defined by Java EE as
- a base type for defining collapsed strings. When schemas
- require trailing/leading space elimination as well as
- collapsing the existing whitespace, this base type may be
- used.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This simple type designates a boolean with only two
- permissible values
-
- - true
- - false
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The url-patternType contains the url pattern of the mapping.
- It must follow the rules specified in Section 11.2 of the
- Servlet API Specification. This pattern is assumed to be in
- URL-decoded form and must not contain CR(#xD) or LF(#xA).
- If it contains those characters, the container must inform
- the developer with a descriptive error message.
- The container must preserve all characters including whitespaces.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- CorporateStocks
-
-
-
- ]]>
-
-
-
-
-
-
-
-
- The message-destination-name element specifies a
- name for a message destination. This name must be
- unique among the names of message destinations
- within the Deployment File.
-
-
-
-
-
-
-
-
- A product specific name that this message destination
- should be mapped to. Each message-destination-ref
- element that references this message destination will
- define a name in the namespace of the referencing
- component or in one of the other predefined namespaces.
- Many application servers provide a way to map these
- local names to names of resources known to the
- application server. This mapped name is often a global
- JNDI name, but may be a name of any form. Each of the
- local names should be mapped to this same global name.
-
- Application servers are not required to support any
- particular form or type of mapped name, nor the ability
- to use mapped names. The mapped name is
- product-dependent and often installation-dependent. No
- use of a mapped name is portable.
-
-
-
-
-
-
-
-
- The JNDI name to be looked up to resolve the message destination.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- jms/StockQueue
-
- javax.jms.Queue
-
- Consumes
-
- CorporateStocks
-
-
-
- ]]>
-
-
-
-
-
-
-
-
- The message-destination-ref-name element specifies
- the name of a message destination reference; its
- value is the environment entry name used in
- Deployment Component code.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The message-destination-usageType specifies the use of the
- message destination indicated by the reference. The value
- indicates whether messages are consumed from the message
- destination, produced for the destination, or both. The
- Assembler makes use of this information in linking producers
- of a destination with its consumers.
-
- The value of the message-destination-usage element must be
- one of the following:
- Consumes
- Produces
- ConsumesProduces
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- javax.jms.Queue
-
-
- ]]>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The message-destination-linkType is used to link a message
- destination reference or message-driven bean to a message
- destination.
-
- The Assembler sets the value to reflect the flow of messages
- between producers and consumers in the application.
-
- The value must be the message-destination-name of a message
- destination in the same Deployment File or in another
- Deployment File in the same Java EE application unit.
-
- Alternatively, the value may be composed of a path name
- specifying a Deployment File containing the referenced
- message destination with the message-destination-name of the
- destination appended and separated from the path name by
- "#". The path name is relative to the Deployment File
- containing Deployment Component that is referencing the
- message destination. This allows multiple message
- destinations with the same name to be uniquely identified.
-
-
-
-
-
-
-
-
-
diff --git a/hapi-fhir-jpaserver-example/src/main/webapp/WEB-INF/xsd/jsp_2_2.xsd b/hapi-fhir-jpaserver-example/src/main/webapp/WEB-INF/xsd/jsp_2_2.xsd
deleted file mode 100644
index fa41e4266f1..00000000000
--- a/hapi-fhir-jpaserver-example/src/main/webapp/WEB-INF/xsd/jsp_2_2.xsd
+++ /dev/null
@@ -1,389 +0,0 @@
-
-
-
-
-
- DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
-
- Copyright 2003-2009 Sun Microsystems, Inc. All rights reserved.
-
- The contents of this file are subject to the terms of either the
- GNU General Public License Version 2 only ("GPL") or the Common
- Development and Distribution License("CDDL") (collectively, the
- "License"). You may not use this file except in compliance with
- the License. You can obtain a copy of the License at
- https://glassfish.dev.java.net/public/CDDL+GPL.html or
- glassfish/bootstrap/legal/LICENSE.txt. See the License for the
- specific language governing permissions and limitations under the
- License.
-
- When distributing the software, include this License Header
- Notice in each file and include the License file at
- glassfish/bootstrap/legal/LICENSE.txt. Sun designates this
- particular file as subject to the "Classpath" exception as
- provided by Sun in the GPL Version 2 section of the License file
- that accompanied this code. If applicable, add the following
- below the License Header, with the fields enclosed by brackets []
- replaced by your own identifying information:
- "Portions Copyrighted [year] [name of copyright owner]"
-
- Contributor(s):
-
- If you wish your version of this file to be governed by only the
- CDDL or only the GPL Version 2, indicate your decision by adding
- "[Contributor] elects to include this software in this
- distribution under the [CDDL or GPL Version 2] license." If you
- don't indicate a single choice of license, a recipient has the
- option to distribute your version of this file under either the
- CDDL, the GPL Version 2 or to extend the choice of license to its
- licensees as provided above. However, if you add GPL Version 2
- code and therefore, elected the GPL Version 2 license, then the
- option applies only if the new code is made subject to such
- option by the copyright holder.
-
-
-
-
-
-
-
- This is the XML Schema for the JSP 2.2 deployment descriptor
- types. The JSP 2.2 schema contains all the special
- structures and datatypes that are necessary to use JSP files
- from a web application.
-
- The contents of this schema is used by the web-common_3_0.xsd
- file to define JSP specific content.
-
-
-
-
-
-
-
- The following conventions apply to all Java EE
- deployment descriptor elements unless indicated otherwise.
-
- - In elements that specify a pathname to a file within the
- same JAR file, relative filenames (i.e., those not
- starting with "/") are considered relative to the root of
- the JAR file's namespace. Absolute filenames (i.e., those
- starting with "/") also specify names in the root of the
- JAR file's namespace. In general, relative names are
- preferred. The exception is .war files where absolute
- names are preferred for consistency with the Servlet API.
-
-
-
-
-
-
-
-
-
-
-
-
-
- The jsp-configType is used to provide global configuration
- information for the JSP files in a web application. It has
- two subelements, taglib and jsp-property-group.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The jsp-file element contains the full path to a JSP file
- within the web application beginning with a `/'.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The jsp-property-groupType is used to group a number of
- files so they can be given global property information.
- All files so described are deemed to be JSP files. The
- following additional properties can be described:
-
- - Control whether EL is ignored.
- - Control whether scripting elements are invalid.
- - Indicate pageEncoding information.
- - Indicate that a resource is a JSP document (XML).
- - Prelude and Coda automatic includes.
- - Control whether the character sequence #{ is allowed
- when used as a String literal.
- - Control whether template text containing only
- whitespaces must be removed from the response output.
- - Indicate the default contentType information.
- - Indicate the default buffering model for JspWriter
- - Control whether error should be raised for the use of
- undeclared namespaces in a JSP page.
-
-
-
-
-
-
-
-
-
-
- Can be used to easily set the isELIgnored
- property of a group of JSP pages. By default, the
- EL evaluation is enabled for Web Applications using
- a Servlet 2.4 or greater web.xml, and disabled
- otherwise.
-
-
-
-
-
-
-
-
- The valid values of page-encoding are those of the
- pageEncoding page directive. It is a
- translation-time error to name different encodings
- in the pageEncoding attribute of the page directive
- of a JSP page and in a JSP configuration element
- matching the page. It is also a translation-time
- error to name different encodings in the prolog
- or text declaration of a document in XML syntax and
- in a JSP configuration element matching the document.
- It is legal to name the same encoding through
- mulitple mechanisms.
-
-
-
-
-
-
-
-
- Can be used to easily disable scripting in a
- group of JSP pages. By default, scripting is
- enabled.
-
-
-
-
-
-
-
-
- If true, denotes that the group of resources
- that match the URL pattern are JSP documents,
- and thus must be interpreted as XML documents.
- If false, the resources are assumed to not
- be JSP documents, unless there is another
- property group that indicates otherwise.
-
-
-
-
-
-
-
-
- The include-prelude element is a context-relative
- path that must correspond to an element in the
- Web Application. When the element is present,
- the given path will be automatically included (as
- in an include directive) at the beginning of each
- JSP page in this jsp-property-group.
-
-
-
-
-
-
-
-
- The include-coda element is a context-relative
- path that must correspond to an element in the
- Web Application. When the element is present,
- the given path will be automatically included (as
- in an include directive) at the end of each
- JSP page in this jsp-property-group.
-
-
-
-
-
-
-
-
- The character sequence #{ is reserved for EL expressions.
- Consequently, a translation error occurs if the #{
- character sequence is used as a String literal, unless
- this element is enabled (true). Disabled (false) by
- default.
-
-
-
-
-
-
-
-
- Indicates that template text containing only whitespaces
- must be removed from the response output. It has no
- effect on JSP documents (XML syntax). Disabled (false)
- by default.
-
-
-
-
-
-
-
-
- The valid values of default-content-type are those of the
- contentType page directive. It specifies the default
- response contentType if the page directive does not include
- a contentType attribute.
-
-
-
-
-
-
-
-
- The valid values of buffer are those of the
- buffer page directive. It specifies if buffering should be
- used for the output to response, and if so, the size of the
- buffer to use.
-
-
-
-
-
-
-
-
- The default behavior when a tag with unknown namespace is used
- in a JSP page (regular syntax) is to silently ignore it. If
- set to true, then an error must be raised during the translation
- time when an undeclared tag is used in a JSP page. Disabled
- (false) by default.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The taglibType defines the syntax for declaring in
- the deployment descriptor that a tag library is
- available to the application. This can be done
- to override implicit map entries from TLD files and
- from the container.
-
-
-
-
-
-
-
-
- A taglib-uri element describes a URI identifying a
- tag library used in the web application. The body
- of the taglib-uri element may be either an
- absolute URI specification, or a relative URI.
- There should be no entries in web.xml with the
- same taglib-uri value.
-
-
-
-
-
-
-
-
- the taglib-location element contains the location
- (as a resource relative to the root of the web
- application) where to find the Tag Library
- Description file for the tag library.
-
-
-
-
-
-
-
-
-
diff --git a/hapi-fhir-jpaserver-example/src/main/webapp/WEB-INF/xsd/web-app_3_0.xsd b/hapi-fhir-jpaserver-example/src/main/webapp/WEB-INF/xsd/web-app_3_0.xsd
deleted file mode 100644
index bbcdf43cd3a..00000000000
--- a/hapi-fhir-jpaserver-example/src/main/webapp/WEB-INF/xsd/web-app_3_0.xsd
+++ /dev/null
@@ -1,272 +0,0 @@
-
-
-
-
-
- DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
-
- Copyright 2003-2009 Sun Microsystems, Inc. All rights reserved.
-
- The contents of this file are subject to the terms of either the
- GNU General Public License Version 2 only ("GPL") or the Common
- Development and Distribution License("CDDL") (collectively, the
- "License"). You may not use this file except in compliance with
- the License. You can obtain a copy of the License at
- https://glassfish.dev.java.net/public/CDDL+GPL.html or
- glassfish/bootstrap/legal/LICENSE.txt. See the License for the
- specific language governing permissions and limitations under the
- License.
-
- When distributing the software, include this License Header
- Notice in each file and include the License file at
- glassfish/bootstrap/legal/LICENSE.txt. Sun designates this
- particular file as subject to the "Classpath" exception as
- provided by Sun in the GPL Version 2 section of the License file
- that accompanied this code. If applicable, add the following
- below the License Header, with the fields enclosed by brackets []
- replaced by your own identifying information:
- "Portions Copyrighted [year] [name of copyright owner]"
-
- Contributor(s):
-
- If you wish your version of this file to be governed by only the
- CDDL or only the GPL Version 2, indicate your decision by adding
- "[Contributor] elects to include this software in this
- distribution under the [CDDL or GPL Version 2] license." If you
- don't indicate a single choice of license, a recipient has the
- option to distribute your version of this file under either the
- CDDL, the GPL Version 2 or to extend the choice of license to its
- licensees as provided above. However, if you add GPL Version 2
- code and therefore, elected the GPL Version 2 license, then the
- option applies only if the new code is made subject to such
- option by the copyright holder.
-
-
-
-
-
-
-
- ...
-
-
- The instance documents may indicate the published version of
- the schema using the xsi:schemaLocation attribute for Java EE
- namespace with the following location:
-
- http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd
-
- ]]>
-
-
-
-
-
-
- The following conventions apply to all Java EE
- deployment descriptor elements unless indicated otherwise.
-
- - In elements that specify a pathname to a file within the
- same JAR file, relative filenames (i.e., those not
- starting with "/") are considered relative to the root of
- the JAR file's namespace. Absolute filenames (i.e., those
- starting with "/") also specify names in the root of the
- JAR file's namespace. In general, relative names are
- preferred. The exception is .war files where absolute
- names are preferred for consistency with the Servlet API.
-
-
-
-
-
-
-
-
-
-
-
-
-
- The web-app element is the root of the deployment
- descriptor for a web application. Note that the sub-elements
- of this element can be in the arbitrary order. Because of
- that, the multiplicity of the elements of distributable,
- session-config, welcome-file-list, jsp-config, login-config,
- and locale-encoding-mapping-list was changed from "?" to "*"
- in this schema. However, the deployment descriptor instance
- file must not contain multiple elements of session-config,
- jsp-config, and login-config. When there are multiple elements of
- welcome-file-list or locale-encoding-mapping-list, the container
- must concatenate the element contents. The multiple occurence
- of the element distributable is redundant and the container
- treats that case exactly in the same way when there is only
- one distributable.
-
-
-
-
-
-
-
- The servlet element contains the name of a servlet.
- The name must be unique within the web application.
-
-
-
-
-
-
-
-
-
-
- The filter element contains the name of a filter.
- The name must be unique within the web application.
-
-
-
-
-
-
-
-
-
-
- The ejb-local-ref-name element contains the name of an EJB
- reference. The EJB reference is an entry in the web
- application's environment and is relative to the
- java:comp/env context. The name must be unique within
- the web application.
-
- It is recommended that name is prefixed with "ejb/".
-
-
-
-
-
-
-
-
-
-
- The ejb-ref-name element contains the name of an EJB
- reference. The EJB reference is an entry in the web
- application's environment and is relative to the
- java:comp/env context. The name must be unique within
- the web application.
-
- It is recommended that name is prefixed with "ejb/".
-
-
-
-
-
-
-
-
-
-
- The resource-env-ref-name element specifies the name of
- a resource environment reference; its value is the
- environment entry name used in the web application code.
- The name is a JNDI name relative to the java:comp/env
- context and must be unique within a web application.
-
-
-
-
-
-
-
-
-
-
- The message-destination-ref-name element specifies the name of
- a message destination reference; its value is the
- environment entry name used in the web application code.
- The name is a JNDI name relative to the java:comp/env
- context and must be unique within a web application.
-
-
-
-
-
-
-
-
-
-
- The res-ref-name element specifies the name of a
- resource manager connection factory reference. The name
- is a JNDI name relative to the java:comp/env context.
- The name must be unique within a web application.
-
-
-
-
-
-
-
-
-
-
- The env-entry-name element contains the name of a web
- application's environment entry. The name is a JNDI
- name relative to the java:comp/env context. The name
- must be unique within a web application.
-
-
-
-
-
-
-
-
-
-
- A role-name-key is specified to allow the references
- from the security-role-refs.
-
-
-
-
-
-
-
-
-
-
- The keyref indicates the references from
- security-role-ref to a specified role-name.
-
-
-
-
-
-
-
-
-
diff --git a/hapi-fhir-jpaserver-example/src/main/webapp/WEB-INF/xsd/web-common_3_0.xsd b/hapi-fhir-jpaserver-example/src/main/webapp/WEB-INF/xsd/web-common_3_0.xsd
deleted file mode 100644
index f994bc2c651..00000000000
--- a/hapi-fhir-jpaserver-example/src/main/webapp/WEB-INF/xsd/web-common_3_0.xsd
+++ /dev/null
@@ -1,1575 +0,0 @@
-
-
-
-
-
- DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
-
- Copyright 2003-2009 Sun Microsystems, Inc. All rights reserved.
-
- The contents of this file are subject to the terms of either the
- GNU General Public License Version 2 only ("GPL") or the Common
- Development and Distribution License("CDDL") (collectively, the
- "License"). You may not use this file except in compliance with
- the License. You can obtain a copy of the License at
- https://glassfish.dev.java.net/public/CDDL+GPL.html or
- glassfish/bootstrap/legal/LICENSE.txt. See the License for the
- specific language governing permissions and limitations under the
- License.
-
- When distributing the software, include this License Header
- Notice in each file and include the License file at
- glassfish/bootstrap/legal/LICENSE.txt. Sun designates this
- particular file as subject to the "Classpath" exception as
- provided by Sun in the GPL Version 2 section of the License file
- that accompanied this code. If applicable, add the following
- below the License Header, with the fields enclosed by brackets []
- replaced by your own identifying information:
- "Portions Copyrighted [year] [name of copyright owner]"
-
- Contributor(s):
-
- If you wish your version of this file to be governed by only the
- CDDL or only the GPL Version 2, indicate your decision by adding
- "[Contributor] elects to include this software in this
- distribution under the [CDDL or GPL Version 2] license." If you
- don't indicate a single choice of license, a recipient has the
- option to distribute your version of this file under either the
- CDDL, the GPL Version 2 or to extend the choice of license to its
- licensees as provided above. However, if you add GPL Version 2
- code and therefore, elected the GPL Version 2 license, then the
- option applies only if the new code is made subject to such
- option by the copyright holder.
-
-
-
-
-
-
-
- ...
-
-
- The instance documents may indicate the published version of
- the schema using the xsi:schemaLocation attribute for Java EE
- namespace with the following location:
-
- http://java.sun.com/xml/ns/javaee/web-common_3_0.xsd
-
- ]]>
-
-
-
-
-
-
- The following conventions apply to all Java EE
- deployment descriptor elements unless indicated otherwise.
-
- - In elements that specify a pathname to a file within the
- same JAR file, relative filenames (i.e., those not
- starting with "/") are considered relative to the root of
- the JAR file's namespace. Absolute filenames (i.e., those
- starting with "/") also specify names in the root of the
- JAR file's namespace. In general, relative names are
- preferred. The exception is .war files where absolute
- names are preferred for consistency with the Servlet API.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The context-param element contains the declaration
- of a web application's servlet context
- initialization parameters.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The metadata-complete attribute defines whether this
- deployment descriptor and other related deployment
- descriptors for this module (e.g., web service
- descriptors) are complete, or whether the class
- files available to this module and packaged with
- this application should be examined for annotations
- that specify deployment information.
-
- If metadata-complete is set to "true", the deployment
- tool must ignore any annotations that specify deployment
- information, which might be present in the class files
- of the application.
-
- If metadata-complete is not specified or is set to
- "false", the deployment tool must examine the class
- files of the application for annotations, as
- specified by the specifications.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The auth-constraintType indicates the user roles that
- should be permitted access to this resource
- collection. The role-name used here must either correspond
- to the role-name of one of the security-role elements
- defined for this web application, or be the specially
- reserved role-name "*" that is a compact syntax for
- indicating all roles in the web application. If both "*"
- and rolenames appear, the container interprets this as all
- roles. If no roles are defined, no user is allowed access
- to the portion of the web application described by the
- containing security-constraint. The container matches
- role names case sensitively when determining access.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The auth-methodType is used to configure the authentication
- mechanism for the web application. As a prerequisite to
- gaining access to any web resources which are protected by
- an authorization constraint, a user must have authenticated
- using the configured mechanism. Legal values are "BASIC",
- "DIGEST", "FORM", "CLIENT-CERT", or a vendor-specific
- authentication scheme.
-
- Used in: login-config
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The dispatcher has five legal values: FORWARD, REQUEST,
- INCLUDE, ASYNC, and ERROR.
-
- A value of FORWARD means the Filter will be applied under
- RequestDispatcher.forward() calls.
- A value of REQUEST means the Filter will be applied under
- ordinary client calls to the path or servlet.
- A value of INCLUDE means the Filter will be applied under
- RequestDispatcher.include() calls.
- A value of ASYNC means the Filter will be applied under
- calls dispatched from an AsyncContext.
- A value of ERROR means the Filter will be applied under the
- error page mechanism.
-
- The absence of any dispatcher elements in a filter-mapping
- indicates a default of applying filters only under ordinary
- client calls to the path or servlet.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The error-code contains an HTTP error code, ex: 404
-
- Used in: error-page
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The error-pageType contains a mapping between an error code
- or exception type to the path of a resource in the web
- application.
-
- Error-page declarations using the exception-type element in
- the deployment descriptor must be unique up to the class name of
- the exception-type. Similarly, error-page declarations using the
- status-code element must be unique in the deployment descriptor
- up to the status code.
-
- Used in: web-app
-
-
-
-
-
-
-
-
-
-
- The exception-type contains a fully qualified class
- name of a Java exception type.
-
-
-
-
-
-
-
-
-
- The location element contains the location of the
- resource in the web application relative to the root of
- the web application. The value of the location must have
- a leading `/'.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The filterType is used to declare a filter in the web
- application. The filter is mapped to either a servlet or a
- URL pattern in the filter-mapping element, using the
- filter-name value to reference. Filters can access the
- initialization parameters declared in the deployment
- descriptor at runtime via the FilterConfig interface.
-
- Used in: web-app
-
-
-
-
-
-
-
-
-
-
- The fully qualified classname of the filter.
-
-
-
-
-
-
-
-
-
- The init-param element contains a name/value pair as
- an initialization param of a servlet filter
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Declaration of the filter mappings in this web
- application is done by using filter-mappingType.
- The container uses the filter-mapping
- declarations to decide which filters to apply to a request,
- and in what order. The container matches the request URI to
- a Servlet in the normal way. To determine which filters to
- apply it matches filter-mapping declarations either on
- servlet-name, or on url-pattern for each filter-mapping
- element, depending on which style is used. The order in
- which filters are invoked is the order in which
- filter-mapping declarations that match a request URI for a
- servlet appear in the list of filter-mapping elements.The
- filter-name value must be the value of the filter-name
- sub-elements of one of the filter declarations in the
- deployment descriptor.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This type defines a string which contains at least one
- character.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The logical name of the filter is declare
- by using filter-nameType. This name is used to map the
- filter. Each filter name is unique within the web
- application.
-
- Used in: filter, filter-mapping
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The form-login-configType specifies the login and error
- pages that should be used in form based login. If form based
- authentication is not used, these elements are ignored.
-
- Used in: login-config
-
-
-
-
-
-
-
-
- The form-login-page element defines the location in the web
- app where the page that can be used for login can be
- found. The path begins with a leading / and is interpreted
- relative to the root of the WAR.
-
-
-
-
-
-
-
-
- The form-error-page element defines the location in
- the web app where the error page that is displayed
- when login is not successful can be found.
- The path begins with a leading / and is interpreted
- relative to the root of the WAR.
-
-
-
-
-
-
-
-
-
-
-
-
- A HTTP method type as defined in HTTP 1.1 section 2.2.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The login-configType is used to configure the authentication
- method that should be used, the realm name that should be
- used for this application, and the attributes that are
- needed by the form login mechanism.
-
- Used in: web-app
-
-
-
-
-
-
-
-
-
- The realm name element specifies the realm name to
- use in HTTP Basic authorization.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The mime-mappingType defines a mapping between an extension
- and a mime type.
-
- Used in: web-app
-
-
-
-
-
-
-
- The extension element contains a string describing an
- extension. example: "txt"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The mime-typeType is used to indicate a defined mime type.
-
- Example:
- "text/plain"
-
- Used in: mime-mapping
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The security-constraintType is used to associate
- security constraints with one or more web resource
- collections
-
- Used in: web-app
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The servletType is used to declare a servlet.
- It contains the declarative data of a
- servlet. If a jsp-file is specified and the load-on-startup
- element is present, then the JSP should be precompiled and
- loaded.
-
- Used in: web-app
-
-
-
-
-
-
-
-
-
-
-
- The servlet-class element contains the fully
- qualified class name of the servlet.
-
-
-
-
-
-
-
-
-
-
-
- The load-on-startup element indicates that this
- servlet should be loaded (instantiated and have
- its init() called) on the startup of the web
- application. The optional contents of these
- element must be an integer indicating the order in
- which the servlet should be loaded. If the value
- is a negative integer, or the element is not
- present, the container is free to load the servlet
- whenever it chooses. If the value is a positive
- integer or 0, the container must load and
- initialize the servlet as the application is
- deployed. The container must guarantee that
- servlets marked with lower integers are loaded
- before servlets marked with higher integers. The
- container may choose the order of loading of
- servlets with the same load-on-start-up value.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The servlet-mappingType defines a mapping between a
- servlet and a url pattern.
-
- Used in: web-app
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The servlet-name element contains the canonical name of the
- servlet. Each servlet name is unique within the web
- application.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The session-configType defines the session parameters
- for this web application.
-
- Used in: web-app
-
-
-
-
-
-
-
-
- The session-timeout element defines the default
- session timeout interval for all sessions created
- in this web application. The specified timeout
- must be expressed in a whole number of minutes.
- If the timeout is 0 or less, the container ensures
- the default behaviour of sessions is never to time
- out. If this element is not specified, the container
- must set its default timeout period.
-
-
-
-
-
-
-
-
- The cookie-config element defines the configuration of the
- session tracking cookies created by this web application.
-
-
-
-
-
-
-
-
- The tracking-mode element defines the tracking modes
- for sessions created by this web application
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The cookie-configType defines the configuration for the
- session tracking cookies of this web application.
-
- Used in: session-config
-
-
-
-
-
-
-
-
- The name that will be assigned to any session tracking
- cookies created by this web application.
- The default is JSESSIONID
-
-
-
-
-
-
-
-
- The domain name that will be assigned to any session tracking
- cookies created by this web application.
-
-
-
-
-
-
-
-
- The path that will be assigned to any session tracking
- cookies created by this web application.
-
-
-
-
-
-
-
-
- The comment that will be assigned to any session tracking
- cookies created by this web application.
-
-
-
-
-
-
-
-
- Specifies whether any session tracking cookies created
- by this web application will be marked as HttpOnly
-
-
-
-
-
-
-
-
- Specifies whether any session tracking cookies created
- by this web application will be marked as secure
- even if the request that initiated the corresponding session
- is using plain HTTP instead of HTTPS
-
-
-
-
-
-
-
-
- The lifetime (in seconds) that will be assigned to any
- session tracking cookies created by this web application.
- Default is -1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The name that will be assigned to any session tracking
- cookies created by this web application.
- The default is JSESSIONID
-
- Used in: cookie-config
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The domain name that will be assigned to any session tracking
- cookies created by this web application.
-
- Used in: cookie-config
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The path that will be assigned to any session tracking
- cookies created by this web application.
-
- Used in: cookie-config
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The comment that will be assigned to any session tracking
- cookies created by this web application.
-
- Used in: cookie-config
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The tracking modes for sessions created by this web
- application
-
- Used in: session-config
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The transport-guaranteeType specifies that the communication
- between client and server should be NONE, INTEGRAL, or
- CONFIDENTIAL. NONE means that the application does not
- require any transport guarantees. A value of INTEGRAL means
- that the application requires that the data sent between the
- client and server be sent in such a way that it can't be
- changed in transit. CONFIDENTIAL means that the application
- requires that the data be transmitted in a fashion that
- prevents other entities from observing the contents of the
- transmission. In most cases, the presence of the INTEGRAL or
- CONFIDENTIAL flag will indicate that the use of SSL is
- required.
-
- Used in: user-data-constraint
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The user-data-constraintType is used to indicate how
- data communicated between the client and container should be
- protected.
-
- Used in: security-constraint
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The elements that use this type designate a path starting
- with a "/" and interpreted relative to the root of a WAR
- file.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This type contains the recognized versions of
- web-application supported. It is used to designate the
- version of the web application.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The web-resource-collectionType is used to identify the
- resources and HTTP methods on those resources to which a
- security constraint applies. If no HTTP methods are specified,
- then the security constraint applies to all HTTP methods.
- If HTTP methods are specified by http-method-omission
- elements, the security constraint applies to all methods
- except those identified in the collection.
- http-method-omission and http-method elements are never
- mixed in the same collection.
-
- Used in: security-constraint
-
-
-
-
-
-
-
-
- The web-resource-name contains the name of this web
- resource collection.
-
-
-
-
-
-
-
-
-
-
-
- Each http-method names an HTTP method to which the
- constraint applies.
-
-
-
-
-
-
-
-
- Each http-method-omission names an HTTP method to
- which the constraint does not apply.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The welcome-file-list contains an ordered list of welcome
- files elements.
-
- Used in: web-app
-
-
-
-
-
-
-
-
- The welcome-file element contains file name to use
- as a default welcome file, such as index.html
-
-
-
-
-
-
-
-
-
-
-
-
- The localeType defines valid locale defined by ISO-639-1
- and ISO-3166.
-
-
-
-
-
-
-
-
-
-
-
-
- The encodingType defines IANA character sets.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The locale-encoding-mapping-list contains one or more
- locale-encoding-mapping(s).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The locale-encoding-mapping contains locale name and
- encoding name. The locale name must be either "Language-code",
- such as "ja", defined by ISO-639 or "Language-code_Country-code",
- such as "ja_JP". "Country code" is defined by ISO-3166.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This element indicates that the ordering sub-element in which
- it was placed should take special action regarding the ordering
- of this application resource relative to other application
- configuration resources.
- See section 8.2.2 of the specification for details.
-
-
-
-
-
-
-
-
-
-
-
-
-
- Please see section 8.2.2 of the specification for details.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Please see section 8.2.2 of the specification for details.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This element contains a sequence of "name" elements, each of
- which
- refers to an application configuration resource by the "name"
- declared on its web.xml fragment. This element can also contain
- a single "others" element which specifies that this document
- comes
- before or after other documents within the application.
- See section 8.2.2 of the specification for details.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- This element specifies configuration information related to the
- handling of multipart/form-data requests.
-
-
-
-
-
-
-
-
- The directory location where uploaded files will be stored
-
-
-
-
-
-
-
-
- The maximum size limit of uploaded files
-
-
-
-
-
-
-
-
- The maximum size limit of multipart/form-data requests
-
-
-
-
-
-
-
-
- The size threshold after which an uploaded file will be
- written to disk
-
-
-
-
-
-
-
-
diff --git a/hapi-fhir-jpaserver-example/src/main/webapp/WEB-INF/xsd/xml.xsd b/hapi-fhir-jpaserver-example/src/main/webapp/WEB-INF/xsd/xml.xsd
deleted file mode 100644
index aea7d0db0a4..00000000000
--- a/hapi-fhir-jpaserver-example/src/main/webapp/WEB-INF/xsd/xml.xsd
+++ /dev/null
@@ -1,287 +0,0 @@
-
-
-
-
-
-
-
-
About the XML namespace
-
-
-
- This schema document describes the XML namespace, in a form
- suitable for import by other schema documents.
-
- Note that local names in this namespace are intended to be
- defined only by the World Wide Web Consortium or its subgroups.
- The names currently defined in this namespace are listed below.
- They should not be used with conflicting semantics by any Working
- Group, specification, or document instance.
-
- denotes an attribute whose value
- is a language code for the natural language of the content of
- any element; its value is inherited. This name is reserved
- by virtue of its definition in the XML specification.
-
-
-
-
Notes
-
- Attempting to install the relevant ISO 2- and 3-letter
- codes as the enumerated possible values is probably never
- going to be a realistic possibility.
-
- The union allows for the 'un-declaration' of xml:lang with
- the empty string.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
space (as an attribute name)
-
- denotes an attribute whose
- value is a keyword indicating what whitespace processing
- discipline is intended for the content of the element; its
- value is inherited. This name is reserved by virtue of its
- definition in the XML specification.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
base (as an attribute name)
-
- denotes an attribute whose value
- provides a URI to be used as the base for interpreting any
- relative URIs in the scope of the element on which it
- appears; its value is inherited. This name is reserved
- by virtue of its definition in the XML Base specification.
- denotes an attribute whose value
- should be interpreted as if declared to be of type ID.
- This name is reserved by virtue of its definition in the
- xml:id specification.
- denotes Jon Bosak, the chair of
- the original XML Working Group. This name is reserved by
- the following decision of the W3C XML Plenary and
- XML Coordination groups:
-
-
-
- In appreciation for his vision, leadership and
- dedication the W3C XML Plenary on this 10th day of
- February, 2000, reserves for Jon Bosak in perpetuity
- the XML name "xml:Father".
-
- This schema defines attributes and an attribute group suitable
- for use by schemas wishing to allow xml:base,
- xml:lang, xml:space or
- xml:id attributes on elements they define.
-
-
- To enable this, such a schema must import this schema for
- the XML namespace, e.g. as follows:
-
- The schema document at that URI may however change in the future,
- in order to remain compatible with the latest version of XML
- Schema itself, or with the XML namespace itself. In other words,
- if the XML Schema or XML namespaces change, the version of this
- document at
- http://www.w3.org/2001/xml.xsd
-
- will change accordingly; the version at
-
- http://www.w3.org/2009/01/xml.xsd
-
- will not change.
-
-
- Previous dated (and unchanging) versions of this schema
- document are at:
-
-
-
-
-
-
diff --git a/hapi-fhir-jpaserver-example/src/test/java/ca/uhn/fhir/jpa/demo/ExampleServerIT.java b/hapi-fhir-jpaserver-example/src/test/java/ca/uhn/fhir/jpa/demo/ExampleServerIT.java
deleted file mode 100644
index 210cb7a0650..00000000000
--- a/hapi-fhir-jpaserver-example/src/test/java/ca/uhn/fhir/jpa/demo/ExampleServerIT.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package ca.uhn.fhir.jpa.demo;
-
-import static org.junit.Assert.assertEquals;
-
-import java.io.File;
-import java.io.IOException;
-
-import ca.uhn.fhir.test.utilities.JettyUtil;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.webapp.WebAppContext;
-import org.hl7.fhir.dstu3.model.Patient;
-import org.hl7.fhir.instance.model.api.IIdType;
-import org.junit.*;
-
-import ca.uhn.fhir.context.FhirContext;
-import ca.uhn.fhir.rest.client.api.IGenericClient;
-import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum;
-import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
-
-public class ExampleServerIT {
-
- private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExampleServerIT.class);
- private static IGenericClient ourClient;
- private static FhirContext ourCtx = FhirContext.forDstu3();
- private static int ourPort;
-
- private static Server ourServer;
- private static String ourServerBase;
-
- @Test
- public void testCreateAndRead() throws IOException {
- ourLog.info("Base URL is: http://localhost:" + ourPort + "/baseDstu3");
- String methodName = "testCreateResourceConditional";
-
- Patient pt = new Patient();
- pt.addName().setFamily(methodName);
- IIdType id = ourClient.create().resource(pt).execute().getId();
-
- Patient pt2 = ourClient.read().resource(Patient.class).withId(id).execute();
- assertEquals(methodName, pt2.getName().get(0).getFamily());
- }
-
- @AfterClass
- public static void afterClass() throws Exception {
- JettyUtil.closeServer(ourServer);
- }
-
- @BeforeClass
- public static void beforeClass() throws Exception {
- /*
- * This runs under maven, and I'm not sure how else to figure out the target directory from code..
- */
- String path = ExampleServerIT.class.getClassLoader().getResource(".keep_hapi-fhir-jpaserver-example").getPath();
- path = new File(path).getParent();
- path = new File(path).getParent();
- path = new File(path).getParent();
-
- ourLog.info("Project base path is: {}", path);
-
- ourServer = new Server(ourPort);
-
- WebAppContext webAppContext = new WebAppContext();
- webAppContext.setContextPath("/");
- webAppContext.setDescriptor(path + "/src/main/webapp/WEB-INF/web.xml");
- webAppContext.setResourceBase(path + "/target/hapi-fhir-jpaserver-example");
- webAppContext.setParentLoaderPriority(true);
-
- ourServer.setHandler(webAppContext);
- JettyUtil.startServer(ourServer);
- ourPort = JettyUtil.getPortForStartedServer(ourServer);
-
- ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
- ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000);
- ourServerBase = "http://localhost:" + ourPort + "/baseDstu3";
- ourClient = ourCtx.newRestfulGenericClient(ourServerBase);
- ourClient.registerInterceptor(new LoggingInterceptor(true));
-
-
- }
-
- public static void main(String[] theArgs) throws Exception {
- ourPort = 8080;
- beforeClass();
- }
-
-
-}
diff --git a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/util/JpaConstants.java b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/util/JpaConstants.java
index 66f2c5b17ed..1d9fa2d83ce 100644
--- a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/util/JpaConstants.java
+++ b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/util/JpaConstants.java
@@ -24,6 +24,9 @@ import ca.uhn.fhir.rest.api.Constants;
public class JpaConstants {
+ public static final String SUBSCRIPTION_TRIGGERING_PARAM_RESOURCE_ID = "resourceId";
+ public static final String SUBSCRIPTION_TRIGGERING_PARAM_SEARCH_URL = "searchUrl";
+
/**
* Non-instantiable
*/
diff --git a/hapi-fhir-jpaserver-subscription/pom.xml b/hapi-fhir-jpaserver-subscription/pom.xml
index 74f140ae27c..43cd8b96d32 100644
--- a/hapi-fhir-jpaserver-subscription/pom.xml
+++ b/hapi-fhir-jpaserver-subscription/pom.xml
@@ -22,9 +22,14 @@
ca.uhn.hapi.fhir
- hapi-fhir-jpaserver-model
+ hapi-fhir-jpaserver-api${project.version}
+
+ ca.uhn.hapi.fhir
+ hapi-fhir-jpaserver-model
+ ${project.version}
+ ca.uhn.hapi.fhirhapi-fhir-validation
@@ -124,7 +129,11 @@
awaitilitytest
-
+
+ org.springframework
+ spring-tx
+
+
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/config/SubscriptionChannelConfig.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/config/SubscriptionChannelConfig.java
new file mode 100644
index 00000000000..a9408ddc681
--- /dev/null
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/config/SubscriptionChannelConfig.java
@@ -0,0 +1,25 @@
+package ca.uhn.fhir.jpa.subscription.channel.config;
+
+import ca.uhn.fhir.jpa.subscription.channel.queue.IQueueChannelFactory;
+import ca.uhn.fhir.jpa.subscription.channel.queue.LinkedBlockingQueueChannelFactory;
+import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionChannelFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class SubscriptionChannelConfig {
+
+ /**
+ * Create a @Primary @Bean if you need a different implementation
+ */
+ @Bean
+ public IQueueChannelFactory subscribableChannelFactory() {
+ return new LinkedBlockingQueueChannelFactory();
+ }
+
+ @Bean
+ public SubscriptionChannelFactory subscriptionChannelFactory() {
+ return new SubscriptionChannelFactory();
+ }
+
+}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/IQueueChannelFactory.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/IQueueChannelFactory.java
new file mode 100644
index 00000000000..e764be57fe4
--- /dev/null
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/IQueueChannelFactory.java
@@ -0,0 +1,58 @@
+package ca.uhn.fhir.jpa.subscription.channel.queue;
+
+/*-
+ * #%L
+ * HAPI FHIR Subscription Server
+ * %%
+ * Copyright (C) 2014 - 2020 University Health Network
+ * %%
+ * 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%
+ */
+
+import org.springframework.messaging.MessageChannel;
+import org.springframework.messaging.SubscribableChannel;
+
+
+/**
+ * This interface is the factory for Queue Channels, which are the low level abstraction over a
+ * queue (e.g. memory queue, JMS queue, Kafka stream, etc.) for any purpose.
+ */
+public interface IQueueChannelFactory {
+
+ /**
+ * Create a channel that is used to receive messages from the queue.
+ *
+ *
+ * Implementations can choose to return the same object for multiple invocations of this method (and {@link #getOrCreateReceiver(String, Class, int)}
+ * when invoked with the same {@literal theChannelName} if they need to, or they can create a new instance.
+ *
+ */
+ SubscribableChannel getOrCreateReceiver(String theChannelName, Class> theMessageType, int theConcurrentConsumers);
+
+ /**
+ * Create a channel that is used to send messages to the queue.
+ *
+ *
+ * Implementations can choose to return the same object for multiple invocations of this method (and {@link #getOrCreateReceiver(String, Class, int)}
+ * when invoked with the same {@literal theChannelName} if they need to, or they can create a new instance.
+ *
+ */
+ MessageChannel getOrCreateSender(String theChannelName, Class> theMessageType, int theConcurrentConsumers);
+
+ // FIXME: can these be removed?
+ int getDeliveryChannelConcurrentConsumers();
+
+ // FIXME: can these be removed?
+ int getMatchingChannelConcurrentConsumers();
+}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/LinkedBlockingQueueSubscribableChannel.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/LinkedBlockingQueueChannel.java
similarity index 91%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/LinkedBlockingQueueSubscribableChannel.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/LinkedBlockingQueueChannel.java
index ea53e3fd693..4a8b091fba5 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/LinkedBlockingQueueSubscribableChannel.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/LinkedBlockingQueueChannel.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module;
+package ca.uhn.fhir.jpa.subscription.channel.queue;
/*-
* #%L
@@ -34,13 +34,13 @@ import org.springframework.messaging.support.ExecutorSubscribableChannel;
import java.util.ArrayList;
import java.util.concurrent.*;
-public class LinkedBlockingQueueSubscribableChannel implements SubscribableChannel {
- private Logger ourLog = LoggerFactory.getLogger(LinkedBlockingQueueSubscribableChannel.class);
+public class LinkedBlockingQueueChannel implements SubscribableChannel {
+ private Logger ourLog = LoggerFactory.getLogger(LinkedBlockingQueueChannel.class);
private final ExecutorSubscribableChannel mySubscribableChannel;
private final BlockingQueue myQueue;
- public LinkedBlockingQueueSubscribableChannel(BlockingQueue theQueue, String theThreadNamingPattern, int theConcurrentConsumers) {
+ public LinkedBlockingQueueChannel(BlockingQueue theQueue, String theThreadNamingPattern, int theConcurrentConsumers) {
ThreadFactory threadFactory = new BasicThreadFactory.Builder()
.namingPattern(theThreadNamingPattern)
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/LinkedBlockingQueueChannelFactory.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/LinkedBlockingQueueChannelFactory.java
new file mode 100644
index 00000000000..d75809d765a
--- /dev/null
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/LinkedBlockingQueueChannelFactory.java
@@ -0,0 +1,60 @@
+package ca.uhn.fhir.jpa.subscription.channel.queue;
+
+/*-
+ * #%L
+ * HAPI FHIR Subscription Server
+ * %%
+ * Copyright (C) 2014 - 2020 University Health Network
+ * %%
+ * 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%
+ */
+
+import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionConstants;
+import org.springframework.messaging.MessageChannel;
+import org.springframework.messaging.SubscribableChannel;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.LinkedBlockingQueue;
+
+public class LinkedBlockingQueueChannelFactory implements IQueueChannelFactory {
+
+ private Map myChannels = Collections.synchronizedMap(new HashMap<>());
+
+ @Override
+ public SubscribableChannel getOrCreateReceiver(String theChannelName, Class> theMessageType, int theConcurrentConsumers) {
+ return getOrCreateChannel(theChannelName, theConcurrentConsumers);
+ }
+
+ @Override
+ public MessageChannel getOrCreateSender(String theChannelName, Class> theMessageType, int theConcurrentConsumers) {
+ return getOrCreateChannel(theChannelName, theConcurrentConsumers);
+ }
+
+ private SubscribableChannel getOrCreateChannel(String theChannelName, int theConcurrentConsumers) {
+ return myChannels.computeIfAbsent(theChannelName, t ->
+ new LinkedBlockingQueueChannel(new LinkedBlockingQueue<>(SubscriptionConstants.DELIVERY_EXECUTOR_QUEUE_SIZE), theChannelName + "-%d", theConcurrentConsumers));
+ }
+
+ @Override
+ public int getDeliveryChannelConcurrentConsumers() {
+ return SubscriptionConstants.DELIVERY_CHANNEL_CONCURRENT_CONSUMERS;
+ }
+
+ @Override
+ public int getMatchingChannelConcurrentConsumers() {
+ return SubscriptionConstants.MATCHING_CHANNEL_CONCURRENT_CONSUMERS;
+ }
+}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/channel/ISubscriptionDeliveryChannelNamer.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/ISubscriptionDeliveryChannelNamer.java
similarity index 86%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/channel/ISubscriptionDeliveryChannelNamer.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/ISubscriptionDeliveryChannelNamer.java
index bf7700db087..4c02e60b056 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/channel/ISubscriptionDeliveryChannelNamer.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/ISubscriptionDeliveryChannelNamer.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module.channel;
+package ca.uhn.fhir.jpa.subscription.channel.subscription;
/*-
* #%L
@@ -20,7 +20,7 @@ package ca.uhn.fhir.jpa.subscription.module.channel;
* #L%
*/
-import ca.uhn.fhir.jpa.subscription.module.CanonicalSubscription;
+import ca.uhn.fhir.jpa.subscription.model.CanonicalSubscription;
public interface ISubscriptionDeliveryChannelNamer {
String nameFromSubscription(CanonicalSubscription theCanonicalSubscription);
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/channel/SubscriptionChannelCache.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelCache.java
similarity index 93%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/channel/SubscriptionChannelCache.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelCache.java
index 5f8f66983ff..142de6b4aeb 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/channel/SubscriptionChannelCache.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelCache.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module.channel;
+package ca.uhn.fhir.jpa.subscription.channel.subscription;
/*-
* #%L
@@ -20,7 +20,7 @@ package ca.uhn.fhir.jpa.subscription.module.channel;
* #L%
*/
-import ca.uhn.fhir.jpa.subscription.module.cache.SubscriptionRegistry;
+import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionRegistry;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelFactory.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelFactory.java
new file mode 100644
index 00000000000..b4c18e2bff9
--- /dev/null
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelFactory.java
@@ -0,0 +1,46 @@
+package ca.uhn.fhir.jpa.subscription.channel.subscription;
+
+/*-
+ * #%L
+ * HAPI FHIR Subscription Server
+ * %%
+ * Copyright (C) 2014 - 2020 University Health Network
+ * %%
+ * 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%
+ */
+
+import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage;
+import ca.uhn.fhir.jpa.subscription.channel.queue.IQueueChannelFactory;
+import ca.uhn.fhir.jpa.subscription.model.ResourceDeliveryMessage;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.messaging.SubscribableChannel;
+
+public class SubscriptionChannelFactory {
+
+ @Autowired
+ private IQueueChannelFactory mySubscribableChannelFactory;
+
+ public SubscribableChannel newDeliveryChannel(String theChannelName) {
+ return mySubscribableChannelFactory.getOrCreateReceiver(theChannelName, ResourceDeliveryMessage.class, mySubscribableChannelFactory.getDeliveryChannelConcurrentConsumers());
+ }
+
+ public SubscribableChannel newMatchingSendingChannel(String theChannelName) {
+ return mySubscribableChannelFactory.getOrCreateReceiver(theChannelName, ResourceModifiedMessage.class, mySubscribableChannelFactory.getMatchingChannelConcurrentConsumers());
+ }
+
+ public SubscribableChannel newMatchingReceivingChannel(String theChannelName) {
+ return mySubscribableChannelFactory.getOrCreateReceiver(theChannelName, ResourceModifiedMessage.class, mySubscribableChannelFactory.getMatchingChannelConcurrentConsumers());
+ }
+
+}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/channel/SubscriptionChannelRegistry.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelRegistry.java
similarity index 94%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/channel/SubscriptionChannelRegistry.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelRegistry.java
index 8dbdfffba09..4a1e782cdee 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/channel/SubscriptionChannelRegistry.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelRegistry.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module.channel;
+package ca.uhn.fhir.jpa.subscription.channel.subscription;
/*-
* #%L
@@ -21,8 +21,8 @@ package ca.uhn.fhir.jpa.subscription.module.channel;
*/
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
-import ca.uhn.fhir.jpa.subscription.module.cache.ActiveSubscription;
-import ca.uhn.fhir.jpa.subscription.module.cache.SubscriptionRegistry;
+import ca.uhn.fhir.jpa.subscription.process.registry.ActiveSubscription;
+import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionRegistry;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Multimap;
import com.google.common.collect.MultimapBuilder;
@@ -31,12 +31,10 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.SubscribableChannel;
-import org.springframework.stereotype.Component;
import java.util.Collection;
import java.util.Optional;
-@Component
public class SubscriptionChannelRegistry {
private static final Logger ourLog = LoggerFactory.getLogger(SubscriptionRegistry.class);
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/channel/SubscriptionChannelWithHandlers.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelWithHandlers.java
similarity index 95%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/channel/SubscriptionChannelWithHandlers.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelWithHandlers.java
index 4e6577d4eba..b262a3b808b 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/channel/SubscriptionChannelWithHandlers.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelWithHandlers.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module.channel;
+package ca.uhn.fhir.jpa.subscription.channel.subscription;
/*-
* #%L
@@ -20,7 +20,7 @@ package ca.uhn.fhir.jpa.subscription.module.channel;
* #L%
*/
-import ca.uhn.fhir.jpa.subscription.module.cache.ActiveSubscription;
+import ca.uhn.fhir.jpa.subscription.process.registry.ActiveSubscription;
import com.google.common.annotations.VisibleForTesting;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/channel/SubscriptionDeliveryChannelNamer.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionDeliveryChannelNamer.java
similarity index 90%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/channel/SubscriptionDeliveryChannelNamer.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionDeliveryChannelNamer.java
index d3a1caca889..42764199a8e 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/channel/SubscriptionDeliveryChannelNamer.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionDeliveryChannelNamer.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module.channel;
+package ca.uhn.fhir.jpa.subscription.channel.subscription;
/*-
* #%L
@@ -20,10 +20,9 @@ package ca.uhn.fhir.jpa.subscription.module.channel;
* #L%
*/
-import ca.uhn.fhir.jpa.subscription.module.CanonicalSubscription;
+import ca.uhn.fhir.jpa.subscription.model.CanonicalSubscription;
import org.springframework.stereotype.Service;
-@Service
public class SubscriptionDeliveryChannelNamer implements ISubscriptionDeliveryChannelNamer {
@Override
public String nameFromSubscription(CanonicalSubscription theCanonicalSubscription) {
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/channel/SubscriptionDeliveryHandlerFactory.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionDeliveryHandlerFactory.java
similarity index 66%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/channel/SubscriptionDeliveryHandlerFactory.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionDeliveryHandlerFactory.java
index 8d62a7fd0be..6c110c616b5 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/channel/SubscriptionDeliveryHandlerFactory.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionDeliveryHandlerFactory.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module.channel;
+package ca.uhn.fhir.jpa.subscription.channel.subscription;
/*-
* #%L
@@ -20,30 +20,30 @@ package ca.uhn.fhir.jpa.subscription.module.channel;
* #L%
*/
-import ca.uhn.fhir.jpa.subscription.module.CanonicalSubscriptionChannelType;
-import ca.uhn.fhir.jpa.subscription.module.subscriber.SubscriptionDeliveringRestHookSubscriber;
-import ca.uhn.fhir.jpa.subscription.module.subscriber.email.IEmailSender;
-import ca.uhn.fhir.jpa.subscription.module.subscriber.email.SubscriptionDeliveringEmailSubscriber;
+import ca.uhn.fhir.jpa.subscription.model.CanonicalSubscriptionChannelType;
+import ca.uhn.fhir.jpa.subscription.process.deliver.email.IEmailSender;
+import ca.uhn.fhir.jpa.subscription.process.deliver.email.SubscriptionDeliveringEmailSubscriber;
+import ca.uhn.fhir.jpa.subscription.process.deliver.resthook.SubscriptionDeliveringRestHookSubscriber;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Lookup;
+import org.springframework.context.ApplicationContext;
import org.springframework.messaging.MessageHandler;
import org.springframework.stereotype.Component;
import java.util.Optional;
-@Component
public class SubscriptionDeliveryHandlerFactory {
private IEmailSender myEmailSender;
- @Lookup
- protected SubscriptionDeliveringEmailSubscriber getSubscriptionDeliveringEmailSubscriber(IEmailSender myEmailSender) {
- // stub method since this is a @Lookup
- throw new IllegalStateException();
+ @Autowired
+ private ApplicationContext myApplicationContext;
+
+ protected SubscriptionDeliveringEmailSubscriber getSubscriptionDeliveringEmailSubscriber(IEmailSender theEmailSender) {
+ return myApplicationContext.getBean(SubscriptionDeliveringEmailSubscriber.class, theEmailSender);
}
- @Lookup
protected SubscriptionDeliveringRestHookSubscriber getSubscriptionDeliveringRestHookSubscriber() {
- // stub method since this is a @Lookup
- throw new IllegalStateException();
+ return myApplicationContext.getBean(SubscriptionDeliveringRestHookSubscriber.class);
}
public Optional createDeliveryHandler(CanonicalSubscriptionChannelType theChannelType) {
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/BaseJsonMessage.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/model/BaseJsonMessage.java
similarity index 95%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/BaseJsonMessage.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/model/BaseJsonMessage.java
index a140978bec3..1bb28358726 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/BaseJsonMessage.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/model/BaseJsonMessage.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module.subscriber;
+package ca.uhn.fhir.jpa.subscription.model;
/*-
* #%L
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/BaseResourceMessage.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/model/BaseResourceMessage.java
similarity index 98%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/BaseResourceMessage.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/model/BaseResourceMessage.java
index fe00948e503..ba753078243 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/BaseResourceMessage.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/model/BaseResourceMessage.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module.subscriber;
+package ca.uhn.fhir.jpa.subscription.model;
/*-
* #%L
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/CanonicalSubscription.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/model/CanonicalSubscription.java
similarity index 99%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/CanonicalSubscription.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/model/CanonicalSubscription.java
index 7ddc2f5f637..a8ba6d41f77 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/CanonicalSubscription.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/model/CanonicalSubscription.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module;
+package ca.uhn.fhir.jpa.subscription.model;
/*-
* #%L
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/CanonicalSubscriptionChannelType.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/model/CanonicalSubscriptionChannelType.java
similarity index 99%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/CanonicalSubscriptionChannelType.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/model/CanonicalSubscriptionChannelType.java
index 474fd3ac1e3..6c523562f82 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/CanonicalSubscriptionChannelType.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/model/CanonicalSubscriptionChannelType.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module;
+package ca.uhn.fhir.jpa.subscription.model;
/*-
* #%L
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/IResourceMessage.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/model/IResourceMessage.java
similarity index 92%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/IResourceMessage.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/model/IResourceMessage.java
index 6bc41c53e4d..0881b8021c5 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/IResourceMessage.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/model/IResourceMessage.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module.subscriber;
+package ca.uhn.fhir.jpa.subscription.model;
/*-
* #%L
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/ResourceDeliveryJsonMessage.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/model/ResourceDeliveryJsonMessage.java
similarity index 96%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/ResourceDeliveryJsonMessage.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/model/ResourceDeliveryJsonMessage.java
index fdeaef18d67..81bd263ec23 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/ResourceDeliveryJsonMessage.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/model/ResourceDeliveryJsonMessage.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module.subscriber;
+package ca.uhn.fhir.jpa.subscription.model;
/*-
* #%L
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/ResourceDeliveryMessage.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/model/ResourceDeliveryMessage.java
similarity index 95%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/ResourceDeliveryMessage.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/model/ResourceDeliveryMessage.java
index 51e9d752ce8..69b40d7004a 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/ResourceDeliveryMessage.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/model/ResourceDeliveryMessage.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module.subscriber;
+package ca.uhn.fhir.jpa.subscription.model;
/*-
* #%L
@@ -21,8 +21,6 @@ package ca.uhn.fhir.jpa.subscription.module.subscriber;
*/
import ca.uhn.fhir.context.FhirContext;
-import ca.uhn.fhir.jpa.subscription.module.CanonicalSubscription;
-import ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage;
import ca.uhn.fhir.rest.api.EncodingEnum;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/ResourceModifiedJsonMessage.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/model/ResourceModifiedJsonMessage.java
similarity index 92%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/ResourceModifiedJsonMessage.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/model/ResourceModifiedJsonMessage.java
index 9a0c2be5c72..f8b8407d686 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/ResourceModifiedJsonMessage.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/model/ResourceModifiedJsonMessage.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module.subscriber;
+package ca.uhn.fhir.jpa.subscription.model;
/*-
* #%L
@@ -20,7 +20,6 @@ package ca.uhn.fhir.jpa.subscription.module.subscriber;
* #L%
*/
-import ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.apache.commons.lang3.builder.ToStringBuilder;
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/ResourceModifiedMessage.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/model/ResourceModifiedMessage.java
similarity index 96%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/ResourceModifiedMessage.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/model/ResourceModifiedMessage.java
index 2bda901b43b..b72ad8ddc1a 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/ResourceModifiedMessage.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/model/ResourceModifiedMessage.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module;
+package ca.uhn.fhir.jpa.subscription.model;
/*-
* #%L
@@ -21,8 +21,6 @@ package ca.uhn.fhir.jpa.subscription.module;
*/
import ca.uhn.fhir.context.FhirContext;
-import ca.uhn.fhir.jpa.subscription.module.subscriber.BaseResourceMessage;
-import ca.uhn.fhir.jpa.subscription.module.subscriber.IResourceMessage;
import ca.uhn.fhir.model.api.IModelJson;
import ca.uhn.fhir.util.ResourceReferenceInfo;
import com.fasterxml.jackson.annotation.JsonIgnore;
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/cache/LinkedBlockingQueueSubscribableChannelFactory.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/cache/LinkedBlockingQueueSubscribableChannelFactory.java
deleted file mode 100644
index 472a07a0931..00000000000
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/cache/LinkedBlockingQueueSubscribableChannelFactory.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package ca.uhn.fhir.jpa.subscription.module.cache;
-
-/*-
- * #%L
- * HAPI FHIR Subscription Server
- * %%
- * Copyright (C) 2014 - 2020 University Health Network
- * %%
- * 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%
- */
-
-import ca.uhn.fhir.jpa.subscription.module.LinkedBlockingQueueSubscribableChannel;
-import ca.uhn.fhir.jpa.subscription.module.channel.ISubscribableChannelFactory;
-import org.springframework.messaging.SubscribableChannel;
-
-import java.util.concurrent.LinkedBlockingQueue;
-
-public class LinkedBlockingQueueSubscribableChannelFactory implements ISubscribableChannelFactory {
- @Override
- public SubscribableChannel createSubscribableChannel(String theChannelName, Class theMessageType, int theConcurrentConsumers) {
- return new LinkedBlockingQueueSubscribableChannel(new LinkedBlockingQueue<>(SubscriptionConstants.DELIVERY_EXECUTOR_QUEUE_SIZE), theChannelName + "-%d", theConcurrentConsumers);
- }
-
- @Override
- public int getDeliveryChannelConcurrentConsumers() {
- return SubscriptionConstants.DELIVERY_CHANNEL_CONCURRENT_CONSUMERS;
- }
-
- @Override
- public int getMatchingChannelConcurrentConsumers() {
- return SubscriptionConstants.MATCHING_CHANNEL_CONCURRENT_CONSUMERS;
- }
-}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/channel/ISubscribableChannelFactory.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/channel/ISubscribableChannelFactory.java
deleted file mode 100644
index 669401726d7..00000000000
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/channel/ISubscribableChannelFactory.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package ca.uhn.fhir.jpa.subscription.module.channel;
-
-/*-
- * #%L
- * HAPI FHIR Subscription Server
- * %%
- * Copyright (C) 2014 - 2020 University Health Network
- * %%
- * 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%
- */
-
-import org.springframework.messaging.SubscribableChannel;
-
-public interface ISubscribableChannelFactory {
- SubscribableChannel createSubscribableChannel(String theChannelName, Class theMessageType, int theConcurrentConsumers);
-
- int getDeliveryChannelConcurrentConsumers();
-
- int getMatchingChannelConcurrentConsumers();
-}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/channel/SubscriptionChannelFactory.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/channel/SubscriptionChannelFactory.java
deleted file mode 100644
index c2a2eca6589..00000000000
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/channel/SubscriptionChannelFactory.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package ca.uhn.fhir.jpa.subscription.module.channel;
-
-/*-
- * #%L
- * HAPI FHIR Subscription Server
- * %%
- * Copyright (C) 2014 - 2020 University Health Network
- * %%
- * 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%
- */
-
-import ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage;
-import ca.uhn.fhir.jpa.subscription.module.subscriber.ResourceDeliveryMessage;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.messaging.SubscribableChannel;
-
-public class SubscriptionChannelFactory {
-
- @Autowired
- private ISubscribableChannelFactory mySubscribableChannelFactory;
-
- public SubscribableChannel newDeliveryChannel(String theChannelName) {
- return mySubscribableChannelFactory.createSubscribableChannel(theChannelName, ResourceDeliveryMessage.class, mySubscribableChannelFactory.getDeliveryChannelConcurrentConsumers());
- }
-
- public SubscribableChannel newMatchingChannel(String theChannelName) {
- return mySubscribableChannelFactory.createSubscribableChannel(theChannelName, ResourceModifiedMessage.class, mySubscribableChannelFactory.getMatchingChannelConcurrentConsumers());
- }
-}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/standalone/FhirClientResourceRetriever.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/standalone/FhirClientResourceRetriever.java
deleted file mode 100644
index c7a27d05851..00000000000
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/standalone/FhirClientResourceRetriever.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package ca.uhn.fhir.jpa.subscription.module.standalone;
-
-/*-
- * #%L
- * HAPI FHIR Subscription Server
- * %%
- * Copyright (C) 2014 - 2020 University Health Network
- * %%
- * 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%
- */
-
-import ca.uhn.fhir.context.FhirContext;
-import ca.uhn.fhir.context.RuntimeResourceDefinition;
-import ca.uhn.fhir.jpa.subscription.module.subscriber.IResourceRetriever;
-import ca.uhn.fhir.rest.client.api.IGenericClient;
-import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
-import org.hl7.fhir.instance.model.api.IBaseResource;
-import org.hl7.fhir.instance.model.api.IIdType;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-public class FhirClientResourceRetriever implements IResourceRetriever {
- private static final Logger ourLog = LoggerFactory.getLogger(FhirClientResourceRetriever.class);
-
- @Autowired
- FhirContext myFhirContext;
- @Autowired
- IGenericClient myClient;
-
- @Override
- public IBaseResource getResource(IIdType payloadId) throws ResourceGoneException {
- RuntimeResourceDefinition resourceDef = myFhirContext.getResourceDefinition(payloadId.getResourceType());
-
- return myClient.read().resource(resourceDef.getName()).withId(payloadId).execute();
- }
-}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/standalone/FhirClientSearchParamProvider.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/standalone/FhirClientSearchParamProvider.java
deleted file mode 100644
index 45928ed71f1..00000000000
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/standalone/FhirClientSearchParamProvider.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package ca.uhn.fhir.jpa.subscription.module.standalone;
-
-/*-
- * #%L
- * HAPI FHIR Subscription Server
- * %%
- * Copyright (C) 2014 - 2020 University Health Network
- * %%
- * 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%
- */
-
-import ca.uhn.fhir.context.FhirContext;
-import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
-import ca.uhn.fhir.jpa.searchparam.registry.SearchParamRegistryImpl;
-import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamProvider;
-import ca.uhn.fhir.model.dstu2.valueset.ResourceTypeEnum;
-import ca.uhn.fhir.rest.api.CacheControlDirective;
-import ca.uhn.fhir.rest.api.server.IBundleProvider;
-import ca.uhn.fhir.rest.client.api.IGenericClient;
-import ca.uhn.fhir.rest.server.SimpleBundleProvider;
-import ca.uhn.fhir.util.BundleUtil;
-import org.hl7.fhir.instance.model.api.IBaseBundle;
-import org.hl7.fhir.instance.model.api.IBaseResource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-public class FhirClientSearchParamProvider implements ISearchParamProvider {
- private static final Logger ourLog = LoggerFactory.getLogger(FhirClientSearchParamProvider.class);
-
- private IGenericClient myClient;
-
- /**
- * Constructor
- */
- @Autowired
- public FhirClientSearchParamProvider(IGenericClient theClient) {
- myClient = theClient;
- }
-
- @Override
- public IBundleProvider search(SearchParameterMap theParams) {
- FhirContext fhirContext = myClient.getFhirContext();
-
- IBaseBundle bundle = myClient
- .search()
- .forResource(ResourceTypeEnum.SEARCHPARAMETER.getCode())
- .cacheControl(new CacheControlDirective().setNoCache(true))
- .execute();
-
- return new SimpleBundleProvider(BundleUtil.toListOfResources(fhirContext, bundle));
- }
-
- @Override
- public int refreshCache(SearchParamRegistryImpl theSearchParamRegistry, long theRefreshInterval) {
- return theSearchParamRegistry.doRefresh(theRefreshInterval);
- }
-}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/standalone/FhirClientSubscriptionProvider.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/standalone/FhirClientSubscriptionProvider.java
deleted file mode 100644
index 1e8e8cb0031..00000000000
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/standalone/FhirClientSubscriptionProvider.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package ca.uhn.fhir.jpa.subscription.module.standalone;
-
-/*-
- * #%L
- * HAPI FHIR Subscription Server
- * %%
- * Copyright (C) 2014 - 2020 University Health Network
- * %%
- * 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%
- */
-
-import ca.uhn.fhir.context.FhirContext;
-import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
-import ca.uhn.fhir.jpa.subscription.module.cache.ISubscriptionProvider;
-import ca.uhn.fhir.jpa.subscription.module.cache.SubscriptionRegistry;
-import ca.uhn.fhir.model.dstu2.valueset.ResourceTypeEnum;
-import ca.uhn.fhir.rest.api.CacheControlDirective;
-import ca.uhn.fhir.rest.api.server.IBundleProvider;
-import ca.uhn.fhir.rest.client.api.IGenericClient;
-import ca.uhn.fhir.rest.server.SimpleBundleProvider;
-import ca.uhn.fhir.util.BundleUtil;
-import org.hl7.fhir.instance.model.api.IBaseBundle;
-import org.hl7.fhir.instance.model.api.IBaseResource;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-public class FhirClientSubscriptionProvider implements ISubscriptionProvider {
- @Autowired
- private FhirContext myFhirContext;
- @Autowired
- private SubscriptionRegistry mySubscriptionRegistry;
-
- IGenericClient myClient;
-
- @Autowired
- public FhirClientSubscriptionProvider(IGenericClient theClient) {
- myClient = theClient;
- }
-
- @Override
- public IBundleProvider search(SearchParameterMap theMap) {
- FhirContext fhirContext = myClient.getFhirContext();
-
- String searchURL = ResourceTypeEnum.SUBSCRIPTION.getCode() + theMap.toNormalizedQueryString(myFhirContext);
-
- IBaseBundle bundle = myClient
- .search()
- .byUrl(searchURL)
- .cacheControl(new CacheControlDirective().setNoCache(true))
- .execute();
-
- return new SimpleBundleProvider(BundleUtil.toListOfResources(fhirContext, bundle));
- }
-
- @Override
- public boolean loadSubscription(IBaseResource theResource) {
- return mySubscriptionRegistry.registerSubscriptionUnlessAlreadyRegistered(theResource);
- }
-}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/standalone/StandaloneSubscriptionConfig.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/standalone/StandaloneSubscriptionConfig.java
deleted file mode 100644
index e798406255a..00000000000
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/standalone/StandaloneSubscriptionConfig.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package ca.uhn.fhir.jpa.subscription.module.standalone;
-
-/*-
- * #%L
- * HAPI FHIR Subscription Server
- * %%
- * Copyright (C) 2014 - 2020 University Health Network
- * %%
- * 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%
- */
-
-import ca.uhn.fhir.rest.client.api.IGenericClient;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-// FIXME: rename
-@Configuration
-public class StandaloneSubscriptionConfig {
-
- /**
- * Constructor
- */
- public StandaloneSubscriptionConfig() {
- super();
- }
-
- @Autowired
- private IGenericClient myClient;
-
- @Bean
- public FhirClientResourceRetriever fhirClientResourceRetriever() {
- return new FhirClientResourceRetriever();
- }
-
- @Bean
- public FhirClientSearchParamProvider fhirClientSearchParamProvider() {
- return new FhirClientSearchParamProvider(myClient);
- }
-
- @Bean
- public FhirClientSubscriptionProvider fhirClientSubscriptionProvider() {
- return new FhirClientSubscriptionProvider(myClient);
- }
-
- @Bean
- public StandaloneSubscriptionMessageHandler fhirClientSubscriptionMessageHandler() {
- return new StandaloneSubscriptionMessageHandler();
- }
-
-}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/standalone/StandaloneSubscriptionMessageHandler.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/standalone/StandaloneSubscriptionMessageHandler.java
deleted file mode 100644
index 8841696cccc..00000000000
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/standalone/StandaloneSubscriptionMessageHandler.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package ca.uhn.fhir.jpa.subscription.module.standalone;
-
-/*-
- * #%L
- * HAPI FHIR Subscription Server
- * %%
- * Copyright (C) 2014 - 2020 University Health Network
- * %%
- * 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%
- */
-
-import ca.uhn.fhir.context.FhirContext;
-import ca.uhn.fhir.context.RuntimeResourceDefinition;
-import ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage;
-import ca.uhn.fhir.jpa.subscription.module.cache.SubscriptionCanonicalizer;
-import ca.uhn.fhir.jpa.subscription.module.cache.SubscriptionConstants;
-import ca.uhn.fhir.jpa.subscription.module.cache.SubscriptionRegistry;
-import ca.uhn.fhir.jpa.subscription.module.subscriber.ResourceModifiedJsonMessage;
-import ca.uhn.fhir.jpa.subscription.module.subscriber.SubscriptionMatchingSubscriber;
-import ca.uhn.fhir.model.dstu2.valueset.ResourceTypeEnum;
-import org.hl7.fhir.instance.model.api.IBaseResource;
-import org.hl7.fhir.instance.model.api.IIdType;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.messaging.Message;
-import org.springframework.messaging.MessageHandler;
-import org.springframework.messaging.MessagingException;
-import org.springframework.stereotype.Service;
-
-public class StandaloneSubscriptionMessageHandler implements MessageHandler {
- private static final Logger ourLog = LoggerFactory.getLogger(StandaloneSubscriptionMessageHandler.class);
-
- @Autowired
- FhirContext myFhirContext;
- @Autowired
- SubscriptionMatchingSubscriber mySubscriptionMatchingSubscriber;
- @Autowired
- SubscriptionRegistry mySubscriptionRegistry;
- @Autowired
- SubscriptionCanonicalizer mySubscriptionCanonicalizer;
-
- @Override
- public void handleMessage(Message> theMessage) throws MessagingException {
- if (!(theMessage instanceof ResourceModifiedJsonMessage)) {
- ourLog.warn("Unexpected message payload type: {}", theMessage);
- return;
- }
- updateSubscriptionRegistryAndPerformMatching(((ResourceModifiedJsonMessage) theMessage).getPayload());
- }
-
- public void updateSubscriptionRegistryAndPerformMatching(ResourceModifiedMessage theResourceModifiedMessage) {
- switch (theResourceModifiedMessage.getOperationType()) {
- case DELETE:
- if (isSubscription(theResourceModifiedMessage)) {
- mySubscriptionRegistry.unregisterSubscription(theResourceModifiedMessage.getId(myFhirContext).getIdPart());
- }
- return;
- case CREATE:
- case UPDATE:
- if (isSubscription(theResourceModifiedMessage)) {
- registerActiveSubscription(theResourceModifiedMessage.getNewPayload(myFhirContext));
- }
- break;
- default:
- break;
- }
-
- mySubscriptionMatchingSubscriber.matchActiveSubscriptionsAndDeliver(theResourceModifiedMessage);
- }
-
- private boolean isSubscription(ResourceModifiedMessage theResourceModifiedMessage) {
- String resourceType;
- IIdType id = theResourceModifiedMessage.getId(myFhirContext);
- if (id != null) {
- resourceType = id.getResourceType();
- } else {
- resourceType = theResourceModifiedMessage.getNewPayload(myFhirContext).getIdElement().getResourceType();
- }
- if (resourceType == null) {
- return false;
- }
- RuntimeResourceDefinition resourceDef = myFhirContext.getResourceDefinition(resourceType);
- return resourceDef.getName().equals(ResourceTypeEnum.SUBSCRIPTION.getCode());
- }
-
- private void registerActiveSubscription(IBaseResource theSubscription) {
- String status = mySubscriptionCanonicalizer.getSubscriptionStatus(theSubscription);
- if (SubscriptionConstants.ACTIVE_STATUS.equals(status)) {
- mySubscriptionRegistry.registerSubscriptionUnlessAlreadyRegistered(theSubscription);
- }
- }
-}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/config/SubscriptionProcessorConfig.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/config/SubscriptionProcessorConfig.java
new file mode 100644
index 00000000000..d923ce00336
--- /dev/null
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/config/SubscriptionProcessorConfig.java
@@ -0,0 +1,136 @@
+package ca.uhn.fhir.jpa.subscription.process.config;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionChannelRegistry;
+import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionDeliveryChannelNamer;
+import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionDeliveryHandlerFactory;
+import ca.uhn.fhir.jpa.subscription.process.deliver.DaoResourceRetriever;
+import ca.uhn.fhir.jpa.subscription.process.deliver.IResourceRetriever;
+import ca.uhn.fhir.jpa.subscription.process.deliver.resthook.SubscriptionDeliveringRestHookSubscriber;
+import ca.uhn.fhir.jpa.subscription.process.deliver.websocket.WebsocketConnectionValidator;
+import ca.uhn.fhir.jpa.subscription.process.matcher.matching.CompositeInMemoryDaoSubscriptionMatcher;
+import ca.uhn.fhir.jpa.subscription.process.matcher.matching.DaoSubscriptionMatcher;
+import ca.uhn.fhir.jpa.subscription.process.matcher.matching.ISubscriptionMatcher;
+import ca.uhn.fhir.jpa.subscription.process.matcher.matching.InMemorySubscriptionMatcher;
+import ca.uhn.fhir.jpa.subscription.process.matcher.matching.SubscriptionStrategyEvaluator;
+import ca.uhn.fhir.jpa.subscription.process.matcher.subscriber.MatchingQueueSubscriberLoader;
+import ca.uhn.fhir.jpa.subscription.process.matcher.subscriber.SubscriptionActivatingSubscriber;
+import ca.uhn.fhir.jpa.subscription.process.matcher.subscriber.SubscriptionMatchingSubscriber;
+import ca.uhn.fhir.jpa.subscription.process.matcher.subscriber.SubscriptionRegisteringSubscriber;
+import ca.uhn.fhir.jpa.subscription.process.registry.DaoSubscriptionProvider;
+import ca.uhn.fhir.jpa.subscription.process.registry.ISubscriptionProvider;
+import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionCanonicalizer;
+import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionLoader;
+import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionRegistry;
+import ca.uhn.fhir.jpa.subscription.triggering.ISubscriptionTriggeringSvc;
+import ca.uhn.fhir.jpa.subscription.triggering.SubscriptionTriggeringSvcImpl;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.context.annotation.Primary;
+import org.springframework.context.annotation.Scope;
+
+/**
+ * This Spring config should be imported by a system that pulls messages off of the
+ * matching queue for processing, and handles delivery
+ */
+public class SubscriptionProcessorConfig {
+
+ @Bean
+ public SubscriptionMatchingSubscriber subscriptionMatchingSubscriber() {
+ return new SubscriptionMatchingSubscriber();
+ }
+
+ @Bean
+ public SubscriptionActivatingSubscriber subscriptionActivatingSubscriber() {
+ return new SubscriptionActivatingSubscriber();
+ }
+
+ @Bean
+ public MatchingQueueSubscriberLoader subscriptionMatchingSubscriberLoader() {
+ return new MatchingQueueSubscriberLoader();
+ }
+
+ @Bean
+ public SubscriptionRegisteringSubscriber subscriptionRegisteringSubscriber() {
+ return new SubscriptionRegisteringSubscriber();
+ }
+
+ @Bean
+ public SubscriptionRegistry subscriptionRegistry() {
+ return new SubscriptionRegistry();
+ }
+
+ @Bean
+ public SubscriptionDeliveryChannelNamer subscriptionDeliveryChannelNamer() {
+ return new SubscriptionDeliveryChannelNamer();
+ }
+
+ @Bean
+ public ISubscriptionProvider subscriptionProvider() {
+ return new DaoSubscriptionProvider();
+ }
+
+ @Bean
+ public IResourceRetriever resourceRetriever() {
+ return new DaoResourceRetriever();
+ }
+
+ @Bean
+ public WebsocketConnectionValidator websocketConnectionValidator() {
+ return new WebsocketConnectionValidator();
+ }
+
+ @Bean
+ public SubscriptionStrategyEvaluator subscriptionStrategyEvaluator() {
+ return new SubscriptionStrategyEvaluator();
+ }
+
+ @Bean
+ public SubscriptionCanonicalizer subscriptionCanonicalizer(FhirContext theFhirContext) {
+ return new SubscriptionCanonicalizer(theFhirContext);
+ }
+
+ @Bean
+ public SubscriptionLoader subscriptionLoader() {
+ return new SubscriptionLoader();
+ }
+
+ @Bean
+ public SubscriptionChannelRegistry subscriptionChannelRegistry() {
+ return new SubscriptionChannelRegistry();
+ }
+
+ @Bean
+ public SubscriptionDeliveryHandlerFactory subscriptionDeliveryHandlerFactory() {
+ return new SubscriptionDeliveryHandlerFactory();
+ }
+
+ @Bean
+ @Lazy
+ public ISubscriptionTriggeringSvc subscriptionTriggeringSvc() {
+ return new SubscriptionTriggeringSvcImpl();
+ }
+
+ @Bean
+ @Scope("prototype")
+ public SubscriptionDeliveringRestHookSubscriber subscriptionDeliveringRestHookSubscriber() {
+ return new SubscriptionDeliveringRestHookSubscriber();
+ }
+
+ @Bean
+ public InMemorySubscriptionMatcher inMemorySubscriptionMatcher() {
+ return new InMemorySubscriptionMatcher();
+ }
+
+ @Bean
+ public DaoSubscriptionMatcher daoSubscriptionMatcher() {
+ return new DaoSubscriptionMatcher();
+ }
+
+ @Bean
+ @Primary
+ public ISubscriptionMatcher subscriptionMatcher(DaoSubscriptionMatcher theDaoSubscriptionMatcher, InMemorySubscriptionMatcher theInMemorySubscriptionMatcher) {
+ return new CompositeInMemoryDaoSubscriptionMatcher(theDaoSubscriptionMatcher, theInMemorySubscriptionMatcher);
+ }
+
+}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/BaseSubscriptionDeliverySubscriber.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/BaseSubscriptionDeliverySubscriber.java
similarity index 86%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/BaseSubscriptionDeliverySubscriber.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/BaseSubscriptionDeliverySubscriber.java
index 0107adf61ad..d8745eef8d6 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/BaseSubscriptionDeliverySubscriber.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/BaseSubscriptionDeliverySubscriber.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module.subscriber;
+package ca.uhn.fhir.jpa.subscription.process.deliver;
/*-
* #%L
@@ -24,9 +24,10 @@ import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.interceptor.api.HookParams;
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
import ca.uhn.fhir.interceptor.api.Pointcut;
-import ca.uhn.fhir.jpa.subscription.module.CanonicalSubscription;
-import ca.uhn.fhir.jpa.subscription.module.cache.ActiveSubscription;
-import ca.uhn.fhir.jpa.subscription.module.cache.SubscriptionRegistry;
+import ca.uhn.fhir.jpa.subscription.model.CanonicalSubscription;
+import ca.uhn.fhir.jpa.subscription.model.ResourceDeliveryMessage;
+import ca.uhn.fhir.jpa.subscription.process.registry.ActiveSubscription;
+import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionRegistry;
import com.google.common.annotations.VisibleForTesting;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -99,17 +100,17 @@ public abstract class BaseSubscriptionDeliverySubscriber implements MessageHandl
public abstract void handleMessage(ResourceDeliveryMessage theMessage) throws Exception;
@VisibleForTesting
- void setFhirContextForUnitTest(FhirContext theCtx) {
+ public void setFhirContextForUnitTest(FhirContext theCtx) {
myFhirContext = theCtx;
}
@VisibleForTesting
- void setInterceptorBroadcasterForUnitTest(IInterceptorBroadcaster theInterceptorBroadcaster) {
+ public void setInterceptorBroadcasterForUnitTest(IInterceptorBroadcaster theInterceptorBroadcaster) {
myInterceptorBroadcaster = theInterceptorBroadcaster;
}
@VisibleForTesting
- void setSubscriptionRegistryForUnitTest(SubscriptionRegistry theSubscriptionRegistry) {
+ public void setSubscriptionRegistryForUnitTest(SubscriptionRegistry theSubscriptionRegistry) {
mySubscriptionRegistry = theSubscriptionRegistry;
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/DaoResourceRetriever.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/DaoResourceRetriever.java
similarity index 83%
rename from hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/DaoResourceRetriever.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/DaoResourceRetriever.java
index c4f5dcea4d4..d070b5adcba 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/DaoResourceRetriever.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/DaoResourceRetriever.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription;
+package ca.uhn.fhir.jpa.subscription.process.deliver;
/*-
* #%L
@@ -22,19 +22,16 @@ package ca.uhn.fhir.jpa.subscription;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
-import ca.uhn.fhir.jpa.dao.DaoRegistry;
-import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
-import ca.uhn.fhir.jpa.subscription.module.cache.ActiveSubscription;
-import ca.uhn.fhir.jpa.subscription.module.subscriber.IResourceRetriever;
+import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
+import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
+import ca.uhn.fhir.jpa.subscription.process.registry.ActiveSubscription;
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-@Service
public class DaoResourceRetriever implements IResourceRetriever {
private static final Logger ourLog = LoggerFactory.getLogger(ActiveSubscription.class);
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/IResourceRetriever.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/IResourceRetriever.java
similarity index 93%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/IResourceRetriever.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/IResourceRetriever.java
index 939fd5f1bfc..930cc43f880 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/IResourceRetriever.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/IResourceRetriever.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module.subscriber;
+package ca.uhn.fhir.jpa.subscription.process.deliver;
/*-
* #%L
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/email/EmailDetails.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/email/EmailDetails.java
similarity index 96%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/email/EmailDetails.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/email/EmailDetails.java
index 4043255b58c..de8c89a4928 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/email/EmailDetails.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/email/EmailDetails.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module.subscriber.email;
+package ca.uhn.fhir.jpa.subscription.process.deliver.email;
/*-
* #%L
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/email/IEmailSender.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/email/IEmailSender.java
similarity index 92%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/email/IEmailSender.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/email/IEmailSender.java
index ff6d3a9dafb..f6f08d17f8b 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/email/IEmailSender.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/email/IEmailSender.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module.subscriber.email;
+package ca.uhn.fhir.jpa.subscription.process.deliver.email;
/*-
* #%L
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/email/JavaMailEmailSender.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/email/JavaMailEmailSender.java
similarity index 98%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/email/JavaMailEmailSender.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/email/JavaMailEmailSender.java
index df826fa80ff..31f8aaeec6d 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/email/JavaMailEmailSender.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/email/JavaMailEmailSender.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module.subscriber.email;
+package ca.uhn.fhir.jpa.subscription.process.deliver.email;
/*-
* #%L
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/email/SubscriptionDeliveringEmailSubscriber.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/email/SubscriptionDeliveringEmailSubscriber.java
similarity index 92%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/email/SubscriptionDeliveringEmailSubscriber.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/email/SubscriptionDeliveringEmailSubscriber.java
index 79175fd38c6..ce650ccad2f 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/email/SubscriptionDeliveringEmailSubscriber.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/email/SubscriptionDeliveringEmailSubscriber.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module.subscriber.email;
+package ca.uhn.fhir.jpa.subscription.process.deliver.email;
/*-
* #%L
@@ -22,9 +22,9 @@ package ca.uhn.fhir.jpa.subscription.module.subscriber.email;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
-import ca.uhn.fhir.jpa.subscription.module.CanonicalSubscription;
-import ca.uhn.fhir.jpa.subscription.module.subscriber.BaseSubscriptionDeliverySubscriber;
-import ca.uhn.fhir.jpa.subscription.module.subscriber.ResourceDeliveryMessage;
+import ca.uhn.fhir.jpa.subscription.model.CanonicalSubscription;
+import ca.uhn.fhir.jpa.subscription.process.deliver.BaseSubscriptionDeliverySubscriber;
+import ca.uhn.fhir.jpa.subscription.model.ResourceDeliveryMessage;
import ca.uhn.fhir.rest.api.EncodingEnum;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/SubscriptionDeliveringRestHookSubscriber.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/resthook/SubscriptionDeliveringRestHookSubscriber.java
similarity index 95%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/SubscriptionDeliveringRestHookSubscriber.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/resthook/SubscriptionDeliveringRestHookSubscriber.java
index b5e3d84170a..d9514007060 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/SubscriptionDeliveringRestHookSubscriber.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/resthook/SubscriptionDeliveringRestHookSubscriber.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module.subscriber;
+package ca.uhn.fhir.jpa.subscription.process.deliver.resthook;
/*-
* #%L
@@ -21,9 +21,11 @@ package ca.uhn.fhir.jpa.subscription.module.subscriber;
*/
import ca.uhn.fhir.interceptor.api.HookParams;
-import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
-import ca.uhn.fhir.jpa.subscription.module.CanonicalSubscription;
+import ca.uhn.fhir.jpa.subscription.model.CanonicalSubscription;
import ca.uhn.fhir.interceptor.api.Pointcut;
+import ca.uhn.fhir.jpa.subscription.model.ResourceDeliveryMessage;
+import ca.uhn.fhir.jpa.subscription.process.deliver.BaseSubscriptionDeliverySubscriber;
+import ca.uhn.fhir.jpa.subscription.process.deliver.IResourceRetriever;
import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.rest.api.RequestTypeEnum;
import ca.uhn.fhir.rest.client.api.*;
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/websocket/SubscriptionWebsocketHandler.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/websocket/SubscriptionWebsocketHandler.java
similarity index 94%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/websocket/SubscriptionWebsocketHandler.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/websocket/SubscriptionWebsocketHandler.java
index 66900c5c271..e628cdce86e 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/websocket/SubscriptionWebsocketHandler.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/websocket/SubscriptionWebsocketHandler.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module.subscriber.websocket;
+package ca.uhn.fhir.jpa.subscription.process.deliver.websocket;
/*
* #%L
@@ -21,10 +21,10 @@ package ca.uhn.fhir.jpa.subscription.module.subscriber.websocket;
*/
import ca.uhn.fhir.context.FhirContext;
-import ca.uhn.fhir.jpa.subscription.module.cache.ActiveSubscription;
-import ca.uhn.fhir.jpa.subscription.module.channel.SubscriptionChannelRegistry;
-import ca.uhn.fhir.jpa.subscription.module.channel.SubscriptionChannelWithHandlers;
-import ca.uhn.fhir.jpa.subscription.module.subscriber.ResourceDeliveryMessage;
+import ca.uhn.fhir.jpa.subscription.process.registry.ActiveSubscription;
+import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionChannelRegistry;
+import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionChannelWithHandlers;
+import ca.uhn.fhir.jpa.subscription.model.ResourceDeliveryMessage;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.model.IdType;
import org.slf4j.Logger;
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/websocket/WebsocketConnectionValidator.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/websocket/WebsocketConnectionValidator.java
similarity index 85%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/websocket/WebsocketConnectionValidator.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/websocket/WebsocketConnectionValidator.java
index 85ed070204e..0442db66a03 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/websocket/WebsocketConnectionValidator.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/websocket/WebsocketConnectionValidator.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module.subscriber.websocket;
+package ca.uhn.fhir.jpa.subscription.process.deliver.websocket;
/*-
* #%L
@@ -20,17 +20,15 @@ package ca.uhn.fhir.jpa.subscription.module.subscriber.websocket;
* #L%
*/
-import ca.uhn.fhir.jpa.subscription.module.CanonicalSubscriptionChannelType;
-import ca.uhn.fhir.jpa.subscription.module.cache.ActiveSubscription;
-import ca.uhn.fhir.jpa.subscription.module.cache.SubscriptionRegistry;
+import ca.uhn.fhir.jpa.subscription.model.CanonicalSubscriptionChannelType;
+import ca.uhn.fhir.jpa.subscription.process.registry.ActiveSubscription;
+import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionRegistry;
import com.sun.istack.NotNull;
import org.hl7.fhir.r4.model.IdType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-@Service
public class WebsocketConnectionValidator {
private static Logger ourLog = LoggerFactory.getLogger(WebsocketConnectionValidator.class);
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/websocket/WebsocketValidationResponse.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/websocket/WebsocketValidationResponse.java
similarity index 92%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/websocket/WebsocketValidationResponse.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/websocket/WebsocketValidationResponse.java
index b0112a83ee5..483143e8d3d 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/websocket/WebsocketValidationResponse.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/websocket/WebsocketValidationResponse.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module.subscriber.websocket;
+package ca.uhn.fhir.jpa.subscription.process.deliver.websocket;
/*-
* #%L
@@ -20,7 +20,7 @@ package ca.uhn.fhir.jpa.subscription.module.subscriber.websocket;
* #L%
*/
-import ca.uhn.fhir.jpa.subscription.module.cache.ActiveSubscription;
+import ca.uhn.fhir.jpa.subscription.process.registry.ActiveSubscription;
public class WebsocketValidationResponse {
private final boolean myValid;
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dbmatcher/CompositeInMemoryDaoSubscriptionMatcher.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/CompositeInMemoryDaoSubscriptionMatcher.java
similarity index 85%
rename from hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dbmatcher/CompositeInMemoryDaoSubscriptionMatcher.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/CompositeInMemoryDaoSubscriptionMatcher.java
index 6d885a07416..ae13ef2ad0a 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dbmatcher/CompositeInMemoryDaoSubscriptionMatcher.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/CompositeInMemoryDaoSubscriptionMatcher.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.dbmatcher;
+package ca.uhn.fhir.jpa.subscription.process.matcher.matching;
/*-
* #%L
@@ -20,12 +20,10 @@ package ca.uhn.fhir.jpa.subscription.dbmatcher;
* #L%
*/
-import ca.uhn.fhir.jpa.dao.DaoConfig;
+import ca.uhn.fhir.jpa.api.config.DaoConfig;
import ca.uhn.fhir.jpa.searchparam.matcher.InMemoryMatchResult;
-import ca.uhn.fhir.jpa.subscription.module.CanonicalSubscription;
-import ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage;
-import ca.uhn.fhir.jpa.subscription.module.matcher.ISubscriptionMatcher;
-import ca.uhn.fhir.jpa.subscription.module.matcher.InMemorySubscriptionMatcher;
+import ca.uhn.fhir.jpa.subscription.model.CanonicalSubscription;
+import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dbmatcher/DaoSubscriptionMatcher.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/DaoSubscriptionMatcher.java
similarity index 90%
rename from hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dbmatcher/DaoSubscriptionMatcher.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/DaoSubscriptionMatcher.java
index b8bcb6dd972..8299ca9c8fe 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dbmatcher/DaoSubscriptionMatcher.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/DaoSubscriptionMatcher.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.dbmatcher;
+package ca.uhn.fhir.jpa.subscription.process.matcher.matching;
/*-
* #%L
@@ -22,14 +22,13 @@ package ca.uhn.fhir.jpa.subscription.dbmatcher;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
-import ca.uhn.fhir.jpa.dao.DaoRegistry;
-import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
+import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
+import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.matcher.InMemoryMatchResult;
-import ca.uhn.fhir.jpa.subscription.module.CanonicalSubscription;
-import ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage;
-import ca.uhn.fhir.jpa.subscription.module.matcher.ISubscriptionMatcher;
+import ca.uhn.fhir.jpa.subscription.model.CanonicalSubscription;
+import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/IResourceModifiedConsumer.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/IResourceModifiedConsumer.java
similarity index 85%
rename from hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/IResourceModifiedConsumer.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/IResourceModifiedConsumer.java
index 40924bdfbf0..047649909b3 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/IResourceModifiedConsumer.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/IResourceModifiedConsumer.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription;
+package ca.uhn.fhir.jpa.subscription.process.matcher.matching;
/*-
* #%L
@@ -20,7 +20,7 @@ package ca.uhn.fhir.jpa.subscription;
* #L%
*/
-import ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage;
+import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage;
public interface IResourceModifiedConsumer {
void submitResourceModified(ResourceModifiedMessage theMsg);
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/matcher/ISubscriptionMatcher.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/ISubscriptionMatcher.java
similarity index 81%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/matcher/ISubscriptionMatcher.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/ISubscriptionMatcher.java
index 15337a26e21..7545ef16db6 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/matcher/ISubscriptionMatcher.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/ISubscriptionMatcher.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module.matcher;
+package ca.uhn.fhir.jpa.subscription.process.matcher.matching;
/*-
* #%L
@@ -21,8 +21,8 @@ package ca.uhn.fhir.jpa.subscription.module.matcher;
*/
import ca.uhn.fhir.jpa.searchparam.matcher.InMemoryMatchResult;
-import ca.uhn.fhir.jpa.subscription.module.CanonicalSubscription;
-import ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage;
+import ca.uhn.fhir.jpa.subscription.model.CanonicalSubscription;
+import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage;
public interface ISubscriptionMatcher {
InMemoryMatchResult match(CanonicalSubscription subscription, ResourceModifiedMessage msg);
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/matcher/InMemorySubscriptionMatcher.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/InMemorySubscriptionMatcher.java
similarity index 90%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/matcher/InMemorySubscriptionMatcher.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/InMemorySubscriptionMatcher.java
index ca6d3d8e0dd..f81d23a7e98 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/matcher/InMemorySubscriptionMatcher.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/InMemorySubscriptionMatcher.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module.matcher;
+package ca.uhn.fhir.jpa.subscription.process.matcher.matching;
/*-
* #%L
@@ -23,8 +23,8 @@ package ca.uhn.fhir.jpa.subscription.module.matcher;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.searchparam.matcher.InMemoryMatchResult;
import ca.uhn.fhir.jpa.searchparam.matcher.SearchParamMatcher;
-import ca.uhn.fhir.jpa.subscription.module.CanonicalSubscription;
-import ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage;
+import ca.uhn.fhir.jpa.subscription.model.CanonicalSubscription;
+import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/matcher/SubscriptionMatchingStrategy.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/SubscriptionMatchingStrategy.java
similarity index 94%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/matcher/SubscriptionMatchingStrategy.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/SubscriptionMatchingStrategy.java
index f49b7996b63..63303994d9d 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/matcher/SubscriptionMatchingStrategy.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/SubscriptionMatchingStrategy.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module.matcher;
+package ca.uhn.fhir.jpa.subscription.process.matcher.matching;
/*-
* #%L
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/matcher/SubscriptionStrategyEvaluator.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/SubscriptionStrategyEvaluator.java
similarity index 92%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/matcher/SubscriptionStrategyEvaluator.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/SubscriptionStrategyEvaluator.java
index 3c805b537b0..04239f38839 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/matcher/SubscriptionStrategyEvaluator.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/SubscriptionStrategyEvaluator.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module.matcher;
+package ca.uhn.fhir.jpa.subscription.process.matcher.matching;
/*-
* #%L
@@ -23,9 +23,7 @@ package ca.uhn.fhir.jpa.subscription.module.matcher;
import ca.uhn.fhir.jpa.searchparam.matcher.InMemoryMatchResult;
import ca.uhn.fhir.jpa.searchparam.matcher.InMemoryResourceMatcher;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-@Service
public class SubscriptionStrategyEvaluator {
@Autowired
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/BaseSubscriberForSubscriptionResources.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/BaseSubscriberForSubscriptionResources.java
new file mode 100644
index 00000000000..79e207a281f
--- /dev/null
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/BaseSubscriberForSubscriptionResources.java
@@ -0,0 +1,21 @@
+package ca.uhn.fhir.jpa.subscription.process.matcher.subscriber;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage;
+import ca.uhn.fhir.model.dstu2.valueset.ResourceTypeEnum;
+import org.hl7.fhir.instance.model.api.IIdType;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.messaging.MessageHandler;
+
+public abstract class BaseSubscriberForSubscriptionResources implements MessageHandler {
+
+ @Autowired
+ protected FhirContext myFhirContext;
+
+ protected boolean isSubscription(ResourceModifiedMessage theNewResource) {
+ IIdType payloadId = theNewResource.getId(myFhirContext);
+ String payloadIdType = payloadId.getResourceType();
+ return payloadIdType.equals(ResourceTypeEnum.SUBSCRIPTION.getCode());
+ }
+
+}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/MatchingQueueSubscriberLoader.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/MatchingQueueSubscriberLoader.java
new file mode 100644
index 00000000000..a4b7d6ef9cf
--- /dev/null
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/MatchingQueueSubscriberLoader.java
@@ -0,0 +1,71 @@
+package ca.uhn.fhir.jpa.subscription.process.matcher.subscriber;
+
+import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionChannelFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.messaging.MessageHandler;
+import org.springframework.messaging.SubscribableChannel;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+
+/*-
+ * #%L
+ * HAPI FHIR Subscription Server
+ * %%
+ * Copyright (C) 2014 - 2020 University Health Network
+ * %%
+ * 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%
+ */
+
+public class MatchingQueueSubscriberLoader {
+ private Logger ourLog = LoggerFactory.getLogger(MatchingQueueSubscriberLoader.class);
+ public static final String SUBSCRIPTION_MATCHING_CHANNEL_NAME = "subscription-matching";
+
+ @Autowired
+ private SubscriptionMatchingSubscriber mySubscriptionMatchingSubscriber;
+ @Autowired
+ private SubscriptionChannelFactory mySubscriptionChannelFactory;
+ @Autowired
+ private SubscriptionRegisteringSubscriber mySubscriptionRegisteringSubscriber;
+ @Autowired
+ private SubscriptionActivatingSubscriber mySubscriptionActivatingSubscriber;
+
+ protected SubscribableChannel myMatchingChannel;
+
+ @PostConstruct
+ public void start() {
+ if (myMatchingChannel == null) {
+ myMatchingChannel = mySubscriptionChannelFactory.newMatchingReceivingChannel(SUBSCRIPTION_MATCHING_CHANNEL_NAME);
+ }
+ if (myMatchingChannel != null) {
+ myMatchingChannel.subscribe(mySubscriptionMatchingSubscriber);
+ myMatchingChannel.subscribe(mySubscriptionActivatingSubscriber);
+ myMatchingChannel.subscribe(mySubscriptionRegisteringSubscriber);
+ ourLog.info("Subscription Matching Subscriber subscribed to Matching Channel {} with name {}", myMatchingChannel.getClass().getName(), SUBSCRIPTION_MATCHING_CHANNEL_NAME);
+ }
+ }
+
+ @SuppressWarnings("unused")
+ @PreDestroy
+ public void stop() {
+ if (myMatchingChannel != null) {
+ myMatchingChannel.unsubscribe(mySubscriptionMatchingSubscriber);
+ myMatchingChannel.unsubscribe(mySubscriptionActivatingSubscriber);
+ myMatchingChannel.unsubscribe(mySubscriptionRegisteringSubscriber);
+ }
+ }
+
+}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionActivatingInterceptor.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionActivatingSubscriber.java
similarity index 51%
rename from hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionActivatingInterceptor.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionActivatingSubscriber.java
index 421c5b195d5..a1f1dbfb49e 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionActivatingInterceptor.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionActivatingSubscriber.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription;
+package ca.uhn.fhir.jpa.subscription.process.matcher.subscriber;
/*-
* #%L
@@ -20,24 +20,19 @@ package ca.uhn.fhir.jpa.subscription;
* #L%
*/
-import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
-import ca.uhn.fhir.interceptor.api.Hook;
-import ca.uhn.fhir.interceptor.api.Interceptor;
-import ca.uhn.fhir.interceptor.api.Pointcut;
-import ca.uhn.fhir.jpa.api.IDaoRegistry;
-import ca.uhn.fhir.jpa.config.BaseConfig;
-import ca.uhn.fhir.jpa.dao.DaoConfig;
-import ca.uhn.fhir.jpa.dao.DaoRegistry;
-import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
-import ca.uhn.fhir.jpa.subscription.module.CanonicalSubscription;
-import ca.uhn.fhir.jpa.subscription.module.CanonicalSubscriptionChannelType;
-import ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage;
-import ca.uhn.fhir.jpa.subscription.module.cache.SubscriptionCanonicalizer;
-import ca.uhn.fhir.jpa.subscription.module.cache.SubscriptionConstants;
-import ca.uhn.fhir.jpa.subscription.module.cache.SubscriptionRegistry;
-import ca.uhn.fhir.jpa.subscription.module.matcher.SubscriptionMatchingStrategy;
-import ca.uhn.fhir.jpa.subscription.module.matcher.SubscriptionStrategyEvaluator;
+import ca.uhn.fhir.jpa.api.config.DaoConfig;
+import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
+import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
+import ca.uhn.fhir.jpa.subscription.model.CanonicalSubscription;
+import ca.uhn.fhir.jpa.subscription.model.CanonicalSubscriptionChannelType;
+import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage;
+import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionCanonicalizer;
+import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionConstants;
+import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionRegistry;
+import ca.uhn.fhir.jpa.subscription.process.matcher.matching.SubscriptionMatchingStrategy;
+import ca.uhn.fhir.jpa.subscription.process.matcher.matching.SubscriptionStrategyEvaluator;
+import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedJsonMessage;
import ca.uhn.fhir.model.dstu2.valueset.ResourceTypeEnum;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.api.EncodingEnum;
@@ -45,16 +40,15 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.util.SubscriptionUtil;
import com.google.common.annotations.VisibleForTesting;
-import org.hl7.fhir.dstu2.model.Subscription;
import org.hl7.fhir.instance.model.api.IBaseResource;
-import org.hl7.fhir.instance.model.api.IPrimitiveType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.context.annotation.Lazy;
import org.springframework.core.task.AsyncTaskExecutor;
-import org.springframework.stereotype.Service;
+import org.springframework.messaging.Message;
+import org.springframework.messaging.MessageHandler;
+import org.springframework.messaging.MessagingException;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
@@ -74,23 +68,20 @@ import static org.apache.commons.lang3.StringUtils.isBlank;
*
* Also validates criteria. If invalid, rejects the subscription without persisting the subscription.
*/
-@Lazy
-@Interceptor
-public class SubscriptionActivatingInterceptor {
+public class SubscriptionActivatingSubscriber extends BaseSubscriberForSubscriptionResources implements MessageHandler {
private static boolean ourWaitForSubscriptionActivationSynchronouslyForUnitTest;
- private Logger ourLog = LoggerFactory.getLogger(SubscriptionActivatingInterceptor.class);
+ private Logger ourLog = LoggerFactory.getLogger(SubscriptionActivatingSubscriber.class);
@Autowired
private PlatformTransactionManager myTransactionManager;
+ // FIXME: use constant if this is still needed
@Autowired
- @Qualifier(BaseConfig.TASK_EXECUTOR_NAME)
+ @Qualifier("hapiJpaTaskExecutor")
private AsyncTaskExecutor myTaskExecutor;
@Autowired
private SubscriptionRegistry mySubscriptionRegistry;
@Autowired
private DaoRegistry myDaoRegistry;
@Autowired
- private FhirContext myFhirContext;
- @Autowired
private SubscriptionCanonicalizer mySubscriptionCanonicalizer;
@Autowired
private DaoConfig myDaoConfig;
@@ -100,10 +91,35 @@ public class SubscriptionActivatingInterceptor {
/**
* Constructor
*/
- public SubscriptionActivatingInterceptor() {
+ public SubscriptionActivatingSubscriber() {
super();
}
+ @Override
+ public void handleMessage(@Nonnull Message> theMessage) throws MessagingException {
+ if (!(theMessage instanceof ResourceModifiedJsonMessage)) {
+ ourLog.warn("Received message of unexpected type on matching channel: {}", theMessage);
+ return;
+ }
+
+ ResourceModifiedMessage payload = ((ResourceModifiedJsonMessage) theMessage).getPayload();
+ if (!isSubscription(payload)) {
+ return;
+ }
+
+ switch (payload.getOperationType()) {
+ case CREATE:
+ case UPDATE:
+ activateAndRegisterSubscriptionIfRequiredInTransaction(payload.getNewPayload(myFhirContext));
+ break;
+ case DELETE:
+ case MANUALLY_TRIGGERED:
+ default:
+ break;
+ }
+
+ }
+
public boolean activateOrRegisterSubscriptionIfRequired(final IBaseResource theSubscription) {
// Grab the value for "Subscription.channel.type" so we can see if this
// subscriber applies..
@@ -171,8 +187,7 @@ public class SubscriptionActivatingInterceptor {
ourLog.info("Activating subscription {} from status {} to {}", subscription.getIdElement().toUnqualified().getValue(), theRequestedStatus, theActiveStatus);
try {
SubscriptionUtil.setStatus(myFhirContext, subscription, theActiveStatus);
- subscription = subscriptionDao.update(subscription).getResource();
- submitResourceModifiedForUpdate(subscription);
+ subscriptionDao.update(subscription);
return true;
} catch (final UnprocessableEntityException e) {
ourLog.info("Changing status of {} to ERROR", subscription.getIdElement());
@@ -183,149 +198,12 @@ public class SubscriptionActivatingInterceptor {
}
}
- void submitResourceModifiedForUpdate(IBaseResource theNewResource) {
- submitResourceModified(theNewResource, ResourceModifiedMessage.OperationTypeEnum.UPDATE);
- }
-
- @Hook(Pointcut.STORAGE_PRECOMMIT_RESOURCE_UPDATED)
- public void resourceUpdatedPreCommit(IBaseResource theOldResource, IBaseResource theNewResource) {
- submitResourceModified(theNewResource, ResourceModifiedMessage.OperationTypeEnum.UPDATE);
- }
-
- @Hook(Pointcut.STORAGE_PRECOMMIT_RESOURCE_CREATED)
- public void resourceCreatedPreCommit(IBaseResource theResource) {
- submitResourceModified(theResource, ResourceModifiedMessage.OperationTypeEnum.CREATE);
- }
-
- @Hook(Pointcut.STORAGE_PRECOMMIT_RESOURCE_DELETED)
- public void resourceDeletedPreCommit(IBaseResource theResource) {
- submitResourceModified(theResource, ResourceModifiedMessage.OperationTypeEnum.DELETE);
- }
-
- @Hook(Pointcut.STORAGE_PRESTORAGE_RESOURCE_CREATED)
- public void resourceCreatedPreStorage(IBaseResource theResource) {
- if (isSubscription(theResource)) {
- validateSubmittedSubscription(theResource);
- }
- }
-
- @Hook(Pointcut.STORAGE_PRESTORAGE_RESOURCE_UPDATED)
- public void resourceUpdatedPreStorage(IBaseResource theOldResource, IBaseResource theNewResource) {
- if (isSubscription(theNewResource)) {
- validateSubmittedSubscription(theNewResource);
- }
- }
-
- @VisibleForTesting
- @SuppressWarnings("WeakerAccess")
- public void setSubscriptionStrategyEvaluatorForUnitTest(SubscriptionStrategyEvaluator theSubscriptionStrategyEvaluator) {
- mySubscriptionStrategyEvaluator = theSubscriptionStrategyEvaluator;
- }
-
- @SuppressWarnings("WeakerAccess")
- public void validateSubmittedSubscription(IBaseResource theSubscription) {
-
- CanonicalSubscription subscription = mySubscriptionCanonicalizer.canonicalize(theSubscription);
- boolean finished = false;
- if (subscription.getStatus() == null) {
- throw new UnprocessableEntityException("Can not process submitted Subscription - Subscription.status must be populated on this server");
- }
-
- switch (subscription.getStatus()) {
- case REQUESTED:
- case ACTIVE:
- break;
- case ERROR:
- case OFF:
- case NULL:
- finished = true;
- break;
- }
-
- mySubscriptionCanonicalizer.setMatchingStrategyTag(theSubscription, null);
-
- if (!finished) {
-
- String query = subscription.getCriteriaString();
- if (isBlank(query)) {
- throw new UnprocessableEntityException("Subscription.criteria must be populated");
- }
-
- int sep = query.indexOf('?');
- if (sep <= 1) {
- throw new UnprocessableEntityException("Subscription.criteria must be in the form \"{Resource Type}?[params]\"");
- }
-
- String resType = query.substring(0, sep);
- if (resType.contains("/")) {
- throw new UnprocessableEntityException("Subscription.criteria must be in the form \"{Resource Type}?[params]\"");
- }
-
- if (subscription.getChannelType() == null) {
- throw new UnprocessableEntityException("Subscription.channel.type must be populated");
- } else if (subscription.getChannelType() == CanonicalSubscriptionChannelType.RESTHOOK) {
- validateChannelPayload(subscription);
- validateChannelEndpoint(subscription);
- }
-
- if (!myDaoRegistry.isResourceTypeSupported(resType)) {
- throw new UnprocessableEntityException("Subscription.criteria contains invalid/unsupported resource type: " + resType);
- }
-
- try {
- SubscriptionMatchingStrategy strategy = mySubscriptionStrategyEvaluator.determineStrategy(query);
- mySubscriptionCanonicalizer.setMatchingStrategyTag(theSubscription, strategy);
- } catch (InvalidRequestException | DataFormatException e) {
- throw new UnprocessableEntityException("Invalid subscription criteria submitted: " + query + " " + e.getMessage());
- }
-
- if (subscription.getChannelType() == null) {
- throw new UnprocessableEntityException("Subscription.channel.type must be populated on this server");
- }
-
- }
- }
-
- @SuppressWarnings("WeakerAccess")
- protected void validateChannelEndpoint(CanonicalSubscription theResource) {
- if (isBlank(theResource.getEndpointUrl())) {
- throw new UnprocessableEntityException("Rest-hook subscriptions must have Subscription.channel.endpoint defined");
- }
- }
-
- @SuppressWarnings("WeakerAccess")
- protected void validateChannelPayload(CanonicalSubscription theResource) {
- if (!isBlank(theResource.getPayloadString()) && EncodingEnum.forContentType(theResource.getPayloadString()) == null) {
- throw new UnprocessableEntityException("Invalid value for Subscription.channel.payload: " + theResource.getPayloadString());
- }
- }
-
- private void submitResourceModified(IBaseResource theNewResource, ResourceModifiedMessage.OperationTypeEnum theOperationType) {
- if (isSubscription(theNewResource)) {
- submitResourceModified(new ResourceModifiedMessage(myFhirContext, theNewResource, theOperationType));
- }
- }
private boolean isSubscription(IBaseResource theNewResource) {
RuntimeResourceDefinition resourceDefinition = myFhirContext.getResourceDefinition(theNewResource);
return ResourceTypeEnum.SUBSCRIPTION.getCode().equals(resourceDefinition.getName());
}
- private void submitResourceModified(final ResourceModifiedMessage theMsg) {
- switch (theMsg.getOperationType()) {
- case DELETE:
- mySubscriptionRegistry.unregisterSubscription(theMsg.getId(myFhirContext).getIdPart());
- break;
- case CREATE:
- case UPDATE:
- activateAndRegisterSubscriptionIfRequiredInTransaction(theMsg.getNewPayload(myFhirContext));
- break;
- case MANUALLY_TRIGGERED:
- default:
- break;
- }
- }
-
private void activateAndRegisterSubscriptionIfRequiredInTransaction(IBaseResource theSubscription) {
TransactionTemplate txTemplate = new TransactionTemplate(myTransactionManager);
txTemplate.execute(new TransactionCallbackWithoutResult() {
@@ -336,19 +214,6 @@ public class SubscriptionActivatingInterceptor {
});
}
- @SuppressWarnings("WeakerAccess")
- @VisibleForTesting
- public void setSubscriptionCanonicalizerForUnitTest(SubscriptionCanonicalizer theSubscriptionCanonicalizer) {
- mySubscriptionCanonicalizer = theSubscriptionCanonicalizer;
- }
-
- @SuppressWarnings("WeakerAccess")
- @VisibleForTesting
- public void setDaoRegistryForUnitTest(DaoRegistry theDaoRegistry) {
- myDaoRegistry = theDaoRegistry;
- }
-
-
@VisibleForTesting
public static void setWaitForSubscriptionActivationSynchronouslyForUnitTest(boolean theWaitForSubscriptionActivationSynchronouslyForUnitTest) {
ourWaitForSubscriptionActivationSynchronouslyForUnitTest = theWaitForSubscriptionActivationSynchronouslyForUnitTest;
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/SubscriptionMatchingSubscriber.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionMatchingSubscriber.java
similarity index 89%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/SubscriptionMatchingSubscriber.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionMatchingSubscriber.java
index 0401be75496..2f8ff1632a8 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/subscriber/SubscriptionMatchingSubscriber.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionMatchingSubscriber.java
@@ -1,17 +1,19 @@
-package ca.uhn.fhir.jpa.subscription.module.subscriber;
+package ca.uhn.fhir.jpa.subscription.process.matcher.subscriber;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.interceptor.api.HookParams;
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
import ca.uhn.fhir.interceptor.api.Pointcut;
import ca.uhn.fhir.jpa.searchparam.matcher.InMemoryMatchResult;
-import ca.uhn.fhir.jpa.subscription.module.CanonicalSubscription;
-import ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage;
-import ca.uhn.fhir.jpa.subscription.module.cache.ActiveSubscription;
-import ca.uhn.fhir.jpa.subscription.module.cache.SubscriptionRegistry;
-import ca.uhn.fhir.jpa.subscription.module.channel.SubscriptionChannelRegistry;
-import ca.uhn.fhir.jpa.subscription.module.matcher.ISubscriptionMatcher;
-import ca.uhn.fhir.rest.api.Constants;
+import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionChannelRegistry;
+import ca.uhn.fhir.jpa.subscription.model.CanonicalSubscription;
+import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage;
+import ca.uhn.fhir.jpa.subscription.process.registry.ActiveSubscription;
+import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionRegistry;
+import ca.uhn.fhir.jpa.subscription.process.matcher.matching.ISubscriptionMatcher;
+import ca.uhn.fhir.jpa.subscription.model.ResourceDeliveryJsonMessage;
+import ca.uhn.fhir.jpa.subscription.model.ResourceDeliveryMessage;
+import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedJsonMessage;
import ca.uhn.fhir.rest.api.EncodingEnum;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.instance.model.api.IBaseResource;
@@ -23,8 +25,8 @@ import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.MessagingException;
-import org.springframework.stereotype.Service;
+import javax.annotation.Nonnull;
import java.util.Collection;
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
@@ -50,9 +52,9 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
* #L%
*/
-@Service
public class SubscriptionMatchingSubscriber implements MessageHandler {
private Logger ourLog = LoggerFactory.getLogger(SubscriptionMatchingSubscriber.class);
+ public static final String SUBSCRIPTION_MATCHING_CHANNEL_NAME = "subscription-matching";
@Autowired
private ISubscriptionMatcher mySubscriptionMatcher;
@@ -65,8 +67,9 @@ public class SubscriptionMatchingSubscriber implements MessageHandler {
@Autowired
private SubscriptionChannelRegistry mySubscriptionChannelRegistry;
+
@Override
- public void handleMessage(Message> theMessage) throws MessagingException {
+ public void handleMessage(@Nonnull Message> theMessage) throws MessagingException {
ourLog.trace("Handling resource modified message: {}", theMessage);
if (!(theMessage instanceof ResourceModifiedJsonMessage)) {
@@ -109,7 +112,6 @@ public class SubscriptionMatchingSubscriber implements MessageHandler {
private void doMatchActiveSubscriptionsAndDeliver(ResourceModifiedMessage theMsg) {
IIdType resourceId = theMsg.getId(myFhirContext);
- Boolean isText = false;
Collection subscriptions = mySubscriptionRegistry.getAll();
@@ -147,7 +149,6 @@ public class SubscriptionMatchingSubscriber implements MessageHandler {
EncodingEnum encoding = null;
if (subscription.getPayloadString() != null && !subscription.getPayloadString().isEmpty()) {
encoding = EncodingEnum.forContentType(subscription.getPayloadString());
- isText = subscription.getPayloadString().equals(Constants.CT_TEXT);
}
encoding = defaultIfNull(encoding, EncodingEnum.JSON);
@@ -179,16 +180,16 @@ public class SubscriptionMatchingSubscriber implements MessageHandler {
}
private boolean sendToDeliveryChannel(ActiveSubscription nextActiveSubscription, ResourceDeliveryMessage theDeliveryMsg) {
- boolean retval = false;
+ boolean retVal = false;
ResourceDeliveryJsonMessage wrappedMsg = new ResourceDeliveryJsonMessage(theDeliveryMsg);
MessageChannel deliveryChannel = mySubscriptionChannelRegistry.get(nextActiveSubscription.getChannelName()).getChannel();
if (deliveryChannel != null) {
- retval = true;
+ retVal = true;
trySendToDeliveryChannel(wrappedMsg, deliveryChannel);
} else {
ourLog.warn("Do not have delivery channel for subscription {}", nextActiveSubscription.getId());
}
- return retval;
+ return retVal;
}
private void trySendToDeliveryChannel(ResourceDeliveryJsonMessage theWrappedMsg, MessageChannel theDeliveryChannel) {
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionRegisteringSubscriber.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionRegisteringSubscriber.java
new file mode 100644
index 00000000000..1273ad8e8a8
--- /dev/null
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionRegisteringSubscriber.java
@@ -0,0 +1,84 @@
+package ca.uhn.fhir.jpa.subscription.process.matcher.subscriber;
+
+/*-
+ * #%L
+ * HAPI FHIR JPA Server
+ * %%
+ * Copyright (C) 2014 - 2020 University Health Network
+ * %%
+ * 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%
+ */
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage;
+import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionRegistry;
+import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedJsonMessage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.messaging.Message;
+import org.springframework.messaging.MessageHandler;
+import org.springframework.messaging.MessagingException;
+
+import javax.annotation.Nonnull;
+
+/**
+ * Responsible for transitioning subscription resources from REQUESTED to ACTIVE
+ * Once activated, the subscription is added to the SubscriptionRegistry.
+ *
+ * Also validates criteria. If invalid, rejects the subscription without persisting the subscription.
+ */
+public class SubscriptionRegisteringSubscriber extends BaseSubscriberForSubscriptionResources implements MessageHandler {
+ private Logger ourLog = LoggerFactory.getLogger(SubscriptionRegisteringSubscriber.class);
+ @Autowired
+ private FhirContext myFhirContext;
+ @Autowired
+ private SubscriptionRegistry mySubscriptionRegistry;
+
+ /**
+ * Constructor
+ */
+ public SubscriptionRegisteringSubscriber() {
+ super();
+ }
+
+ @Override
+ public void handleMessage(@Nonnull Message> theMessage) throws MessagingException {
+ if (!(theMessage instanceof ResourceModifiedJsonMessage)) {
+ ourLog.warn("Received message of unexpected type on matching channel: {}", theMessage);
+ return;
+ }
+
+ ResourceModifiedMessage payload = ((ResourceModifiedJsonMessage) theMessage).getPayload();
+
+ if (!isSubscription(payload)) {
+ return;
+ }
+
+ switch (payload.getOperationType()) {
+ case DELETE:
+ mySubscriptionRegistry.unregisterSubscription(payload.getId(myFhirContext).getIdPart());
+ break;
+ case CREATE:
+ case UPDATE:
+ mySubscriptionRegistry.registerSubscriptionUnlessAlreadyRegistered(payload.getNewPayload(myFhirContext));
+ break;
+ case MANUALLY_TRIGGERED:
+ default:
+ break;
+ }
+
+ }
+
+}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/cache/ActiveSubscription.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/ActiveSubscription.java
similarity index 90%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/cache/ActiveSubscription.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/ActiveSubscription.java
index cdacb3401f5..1ea5160ac6d 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/cache/ActiveSubscription.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/ActiveSubscription.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module.cache;
+package ca.uhn.fhir.jpa.subscription.process.registry;
/*-
* #%L
@@ -20,8 +20,8 @@ package ca.uhn.fhir.jpa.subscription.module.cache;
* #L%
*/
-import ca.uhn.fhir.jpa.subscription.module.CanonicalSubscription;
-import ca.uhn.fhir.jpa.subscription.module.CanonicalSubscriptionChannelType;
+import ca.uhn.fhir.jpa.subscription.model.CanonicalSubscription;
+import ca.uhn.fhir.jpa.subscription.model.CanonicalSubscriptionChannelType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/cache/ActiveSubscriptionCache.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/ActiveSubscriptionCache.java
similarity index 97%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/cache/ActiveSubscriptionCache.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/ActiveSubscriptionCache.java
index 305a1889161..d21161f5370 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/cache/ActiveSubscriptionCache.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/ActiveSubscriptionCache.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module.cache;
+package ca.uhn.fhir.jpa.subscription.process.registry;
/*-
* #%L
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dbcache/DaoSubscriptionProvider.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/DaoSubscriptionProvider.java
similarity index 77%
rename from hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dbcache/DaoSubscriptionProvider.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/DaoSubscriptionProvider.java
index 6931bfd99e9..ad75c98df8e 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dbcache/DaoSubscriptionProvider.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/DaoSubscriptionProvider.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.dbcache;
+package ca.uhn.fhir.jpa.subscription.process.registry;
/*-
* #%L
@@ -20,22 +20,20 @@ package ca.uhn.fhir.jpa.subscription.dbcache;
* #L%
*/
-import ca.uhn.fhir.jpa.dao.DaoRegistry;
-import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
+import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
+import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
-import ca.uhn.fhir.jpa.subscription.SubscriptionActivatingInterceptor;
-import ca.uhn.fhir.jpa.subscription.module.cache.ISubscriptionProvider;
+import ca.uhn.fhir.jpa.subscription.process.matcher.subscriber.SubscriptionActivatingSubscriber;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-@Service
public class DaoSubscriptionProvider implements ISubscriptionProvider {
+
@Autowired
DaoRegistry myDaoRegistry;
@Autowired
- private SubscriptionActivatingInterceptor mySubscriptionActivatingInterceptor;
+ private SubscriptionActivatingSubscriber mySubscriptionActivatingInterceptor;
@Override
public IBundleProvider search(SearchParameterMap theMap) {
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/cache/ISubscriptionProvider.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/ISubscriptionProvider.java
similarity index 94%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/cache/ISubscriptionProvider.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/ISubscriptionProvider.java
index 1f254e919b3..a8afb1ccde4 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/cache/ISubscriptionProvider.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/ISubscriptionProvider.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module.cache;
+package ca.uhn.fhir.jpa.subscription.process.registry;
/*-
* #%L
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/cache/SubscriptionCanonicalizer.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/SubscriptionCanonicalizer.java
similarity index 97%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/cache/SubscriptionCanonicalizer.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/SubscriptionCanonicalizer.java
index a1229b456a5..bd8d75f3cf2 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/cache/SubscriptionCanonicalizer.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/SubscriptionCanonicalizer.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module.cache;
+package ca.uhn.fhir.jpa.subscription.process.registry;
/*-
* #%L
@@ -23,21 +23,23 @@ package ca.uhn.fhir.jpa.subscription.module.cache;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.model.util.JpaConstants;
-import ca.uhn.fhir.jpa.subscription.module.CanonicalSubscription;
-import ca.uhn.fhir.jpa.subscription.module.CanonicalSubscriptionChannelType;
-import ca.uhn.fhir.jpa.subscription.module.matcher.SubscriptionMatchingStrategy;
+import ca.uhn.fhir.jpa.subscription.model.CanonicalSubscription;
+import ca.uhn.fhir.jpa.subscription.model.CanonicalSubscriptionChannelType;
+import ca.uhn.fhir.jpa.subscription.process.matcher.matching.SubscriptionMatchingStrategy;
import ca.uhn.fhir.model.dstu2.resource.Subscription;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.exceptions.FHIRException;
-import org.hl7.fhir.instance.model.api.*;
+import org.hl7.fhir.instance.model.api.IBaseMetaType;
+import org.hl7.fhir.instance.model.api.IBaseReference;
+import org.hl7.fhir.instance.model.api.IBaseResource;
+import org.hl7.fhir.instance.model.api.IPrimitiveType;
import org.hl7.fhir.r4.model.Extension;
import org.hl7.fhir.r5.model.Coding;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -49,7 +51,6 @@ import java.util.stream.Collectors;
import static java.util.stream.Collectors.mapping;
import static java.util.stream.Collectors.toList;
-@Service
public class SubscriptionCanonicalizer {
private static final Logger ourLog = LoggerFactory.getLogger(SubscriptionCanonicalizer.class);
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/cache/SubscriptionConstants.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/SubscriptionConstants.java
similarity index 96%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/cache/SubscriptionConstants.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/SubscriptionConstants.java
index 4c3822cd420..e4f9254c845 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/cache/SubscriptionConstants.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/SubscriptionConstants.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module.cache;
+package ca.uhn.fhir.jpa.subscription.process.registry;
/*-
* #%L
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/cache/SubscriptionLoader.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/SubscriptionLoader.java
similarity index 97%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/cache/SubscriptionLoader.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/SubscriptionLoader.java
index 8a7d09abca2..59e66b77696 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/cache/SubscriptionLoader.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/SubscriptionLoader.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module.cache;
+package ca.uhn.fhir.jpa.subscription.process.registry;
/*-
* #%L
@@ -37,8 +37,6 @@ import org.quartz.JobExecutionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Lazy;
-import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.HashSet;
@@ -47,8 +45,6 @@ import java.util.Set;
import java.util.concurrent.Semaphore;
-@Service
-@Lazy
public class SubscriptionLoader {
private static final Logger ourLog = LoggerFactory.getLogger(SubscriptionLoader.class);
private static final int MAX_RETRIES = 60; // 60 * 5 seconds = 5 minutes
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/cache/SubscriptionRegistry.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/SubscriptionRegistry.java
similarity index 94%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/cache/SubscriptionRegistry.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/SubscriptionRegistry.java
index f507e980034..26edf6f9a44 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/cache/SubscriptionRegistry.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/SubscriptionRegistry.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module.cache;
+package ca.uhn.fhir.jpa.subscription.process.registry;
/*-
* #%L
@@ -23,9 +23,9 @@ package ca.uhn.fhir.jpa.subscription.module.cache;
import ca.uhn.fhir.interceptor.api.HookParams;
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
import ca.uhn.fhir.interceptor.api.Pointcut;
-import ca.uhn.fhir.jpa.subscription.module.CanonicalSubscription;
-import ca.uhn.fhir.jpa.subscription.module.channel.ISubscriptionDeliveryChannelNamer;
-import ca.uhn.fhir.jpa.subscription.module.channel.SubscriptionChannelRegistry;
+import ca.uhn.fhir.jpa.subscription.channel.subscription.ISubscriptionDeliveryChannelNamer;
+import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionChannelRegistry;
+import ca.uhn.fhir.jpa.subscription.model.CanonicalSubscription;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
@@ -33,7 +33,6 @@ import org.hl7.fhir.r4.model.Subscription;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
import javax.annotation.PreDestroy;
import java.util.Collection;
@@ -47,8 +46,6 @@ import java.util.Optional;
* handlers are all caches in this registry so they can be removed it the subscription is deleted.
*/
-// TODO KHS Does jpa need a subscription registry if matching is disabled?
-@Component
public class SubscriptionRegistry {
private static final Logger ourLog = LoggerFactory.getLogger(SubscriptionRegistry.class);
private final ActiveSubscriptionCache myActiveSubscriptionCache = new ActiveSubscriptionCache();
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/config/SubscriptionSubmitterConfig.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/config/SubscriptionSubmitterConfig.java
new file mode 100644
index 00000000000..eab841e50b2
--- /dev/null
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/config/SubscriptionSubmitterConfig.java
@@ -0,0 +1,31 @@
+package ca.uhn.fhir.jpa.subscription.submit.config;
+
+import ca.uhn.fhir.jpa.subscription.submit.interceptor.SubscriptionMatcherInterceptor;
+import ca.uhn.fhir.jpa.subscription.submit.interceptor.SubmitInterceptorLoader;
+import ca.uhn.fhir.jpa.subscription.submit.interceptor.SubscriptionValidatingInterceptor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * This Spring config should be imported by a system that submits resources to the
+ * matching queue for processing
+ */
+@Configuration
+public class SubscriptionSubmitterConfig {
+
+ @Bean
+ public SubscriptionMatcherInterceptor subscriptionMatcherInterceptor() {
+ return new SubscriptionMatcherInterceptor();
+ }
+
+ @Bean
+ public SubscriptionValidatingInterceptor subscriptionValidatingInterceptor() {
+ return new SubscriptionValidatingInterceptor();
+ }
+
+ @Bean
+ public SubmitInterceptorLoader subscriptionMatcherInterceptorLoader() {
+ return new SubmitInterceptorLoader();
+ }
+
+}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionInterceptorLoader.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubmitInterceptorLoader.java
similarity index 77%
rename from hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionInterceptorLoader.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubmitInterceptorLoader.java
index ba75e082ee9..af3c7030410 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionInterceptorLoader.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubmitInterceptorLoader.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription;
+package ca.uhn.fhir.jpa.subscription.submit.interceptor;
/*-
* #%L
@@ -21,28 +21,27 @@ package ca.uhn.fhir.jpa.subscription;
*/
import ca.uhn.fhir.interceptor.api.IInterceptorService;
-import ca.uhn.fhir.jpa.dao.DaoConfig;
-import ca.uhn.fhir.jpa.subscription.module.cache.SubscriptionLoader;
-import ca.uhn.fhir.jpa.subscription.module.cache.SubscriptionRegistry;
-import ca.uhn.fhir.jpa.subscription.module.channel.SubscriptionChannelRegistry;
+import ca.uhn.fhir.jpa.api.config.DaoConfig;
+import ca.uhn.fhir.jpa.subscription.process.matcher.subscriber.SubscriptionActivatingSubscriber;
+import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionLoader;
+import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionRegistry;
+import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionChannelRegistry;
import com.google.common.annotations.VisibleForTesting;
import org.hl7.fhir.dstu2.model.Subscription;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
-import org.springframework.stereotype.Service;
import java.util.Set;
-@Service
-public class SubscriptionInterceptorLoader {
- private static final Logger ourLog = LoggerFactory.getLogger(SubscriptionInterceptorLoader.class);
+public class SubmitInterceptorLoader {
+ private static final Logger ourLog = LoggerFactory.getLogger(SubmitInterceptorLoader.class);
@Autowired
private SubscriptionMatcherInterceptor mySubscriptionMatcherInterceptor;
@Autowired
- private SubscriptionActivatingInterceptor mySubscriptionActivatingInterceptor;
+ private SubscriptionValidatingInterceptor mySubscriptionValidatingInterceptor;
@Autowired
DaoConfig myDaoConfig;
@Autowired
@@ -61,14 +60,14 @@ public class SubscriptionInterceptorLoader {
ourLog.info("Subscriptions are disabled on this server. Subscriptions will not be activated and incoming resources will not be matched against subscriptions.");
} else {
loadSubscriptions();
- ourLog.info("Registering subscription activating interceptor");
- myInterceptorRegistry.registerInterceptor(mySubscriptionActivatingInterceptor);
if (myDaoConfig.isSubscriptionMatchingEnabled()) {
mySubscriptionMatcherInterceptor.start();
ourLog.info("Registering subscription matcher interceptor");
myInterceptorRegistry.registerInterceptor(mySubscriptionMatcherInterceptor);
}
}
+
+ myInterceptorRegistry.registerInterceptor(mySubscriptionValidatingInterceptor);
}
private void loadSubscriptions() {
@@ -81,9 +80,8 @@ public class SubscriptionInterceptorLoader {
}
@VisibleForTesting
- void unregisterInterceptorsForUnitTest() {
- myInterceptorRegistry.unregisterInterceptor(mySubscriptionActivatingInterceptor);
+ public void unregisterInterceptorsForUnitTest() {
myInterceptorRegistry.unregisterInterceptor(mySubscriptionMatcherInterceptor);
- mySubscriptionMatcherInterceptor.preDestroy();
+ myInterceptorRegistry.unregisterInterceptor(mySubscriptionValidatingInterceptor);
}
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionMatcherInterceptor.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionMatcherInterceptor.java
similarity index 74%
rename from hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionMatcherInterceptor.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionMatcherInterceptor.java
index 7f20e410e30..2d88a34a5de 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionMatcherInterceptor.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionMatcherInterceptor.java
@@ -1,12 +1,13 @@
-package ca.uhn.fhir.jpa.subscription;
+package ca.uhn.fhir.jpa.subscription.submit.interceptor;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.interceptor.api.*;
-import ca.uhn.fhir.jpa.subscription.module.LinkedBlockingQueueSubscribableChannel;
-import ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage;
-import ca.uhn.fhir.jpa.subscription.module.channel.SubscriptionChannelFactory;
-import ca.uhn.fhir.jpa.subscription.module.subscriber.ResourceModifiedJsonMessage;
-import ca.uhn.fhir.jpa.subscription.module.subscriber.SubscriptionMatchingSubscriber;
+import ca.uhn.fhir.jpa.subscription.channel.queue.LinkedBlockingQueueChannel;
+import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage;
+import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionChannelFactory;
+import ca.uhn.fhir.jpa.subscription.process.matcher.matching.IResourceModifiedConsumer;
+import ca.uhn.fhir.jpa.subscription.process.matcher.subscriber.SubscriptionMatchingSubscriber;
+import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedJsonMessage;
import ca.uhn.fhir.jpa.util.JpaInterceptorBroadcaster;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import com.google.common.annotations.VisibleForTesting;
@@ -15,13 +16,11 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Lazy;
import org.springframework.messaging.SubscribableChannel;
-import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;
-import javax.annotation.PreDestroy;
+import javax.annotation.PostConstruct;
/*-
* #%L
@@ -43,14 +42,8 @@ import javax.annotation.PreDestroy;
* #L%
*/
-@Component
-@Lazy
-@Interceptor()
+@Interceptor
public class SubscriptionMatcherInterceptor implements IResourceModifiedConsumer {
- public static final String SUBSCRIPTION_MATCHING_CHANNEL_NAME = "subscription-matching";
- protected SubscribableChannel myMatchingChannel;
- @Autowired
- protected SubscriptionChannelFactory mySubscriptionChannelFactory;
private Logger ourLog = LoggerFactory.getLogger(SubscriptionMatcherInterceptor.class);
@Autowired
private FhirContext myFhirContext;
@@ -58,6 +51,10 @@ public class SubscriptionMatcherInterceptor implements IResourceModifiedConsumer
private SubscriptionMatchingSubscriber mySubscriptionMatchingSubscriber;
@Autowired
private IInterceptorBroadcaster myInterceptorBroadcaster;
+ @Autowired
+ private SubscriptionChannelFactory mySubscriptionChannelFactory;
+
+ private SubscribableChannel myMatchingChannel;
/**
* Constructor
@@ -66,22 +63,9 @@ public class SubscriptionMatcherInterceptor implements IResourceModifiedConsumer
super();
}
+ @PostConstruct
public void start() {
- if (myMatchingChannel == null) {
- myMatchingChannel = mySubscriptionChannelFactory.newMatchingChannel(SUBSCRIPTION_MATCHING_CHANNEL_NAME);
- }
- myMatchingChannel.subscribe(mySubscriptionMatchingSubscriber);
- ourLog.info("Subscription Matching Subscriber subscribed to Matching Channel {} with name {}", myMatchingChannel.getClass().getName(), SUBSCRIPTION_MATCHING_CHANNEL_NAME);
-
- }
-
- @SuppressWarnings("unused")
- @PreDestroy
- public void preDestroy() {
-
- if (myMatchingChannel != null) {
- myMatchingChannel.unsubscribe(mySubscriptionMatchingSubscriber);
- }
+ myMatchingChannel = mySubscriptionChannelFactory.newMatchingSendingChannel(SubscriptionMatchingSubscriber.SUBSCRIPTION_MATCHING_CHANNEL_NAME);
}
@Hook(Pointcut.STORAGE_PRECOMMIT_RESOURCE_CREATED)
@@ -101,6 +85,7 @@ public class SubscriptionMatcherInterceptor implements IResourceModifiedConsumer
private void submitResourceModified(IBaseResource theNewResource, ResourceModifiedMessage.OperationTypeEnum theOperationType, RequestDetails theRequest) {
ResourceModifiedMessage msg = new ResourceModifiedMessage(myFhirContext, theNewResource, theOperationType);
+
// Interceptor call: SUBSCRIPTION_RESOURCE_MODIFIED
HookParams params = new HookParams()
.add(ResourceModifiedMessage.class, msg);
@@ -150,7 +135,7 @@ public class SubscriptionMatcherInterceptor implements IResourceModifiedConsumer
}
@VisibleForTesting
- LinkedBlockingQueueSubscribableChannel getProcessingChannelForUnitTest() {
- return (LinkedBlockingQueueSubscribableChannel) myMatchingChannel;
+ public LinkedBlockingQueueChannel getProcessingChannelForUnitTest() {
+ return (LinkedBlockingQueueChannel) myMatchingChannel;
}
}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionValidatingInterceptor.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionValidatingInterceptor.java
new file mode 100644
index 00000000000..efcb902e39d
--- /dev/null
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionValidatingInterceptor.java
@@ -0,0 +1,144 @@
+package ca.uhn.fhir.jpa.subscription.submit.interceptor;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.interceptor.api.Hook;
+import ca.uhn.fhir.interceptor.api.Interceptor;
+import ca.uhn.fhir.interceptor.api.Pointcut;
+import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
+import ca.uhn.fhir.jpa.subscription.model.CanonicalSubscription;
+import ca.uhn.fhir.jpa.subscription.model.CanonicalSubscriptionChannelType;
+import ca.uhn.fhir.jpa.subscription.process.matcher.matching.SubscriptionMatchingStrategy;
+import ca.uhn.fhir.jpa.subscription.process.matcher.matching.SubscriptionStrategyEvaluator;
+import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionCanonicalizer;
+import ca.uhn.fhir.parser.DataFormatException;
+import ca.uhn.fhir.rest.api.EncodingEnum;
+import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
+import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
+import com.google.common.annotations.VisibleForTesting;
+import org.hl7.fhir.instance.model.api.IBaseResource;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import static org.apache.commons.lang3.StringUtils.isBlank;
+
+@Interceptor
+public class SubscriptionValidatingInterceptor {
+
+ @Autowired
+ private SubscriptionCanonicalizer mySubscriptionCanonicalizer;
+ @Autowired
+ private DaoRegistry myDaoRegistry;
+ @Autowired
+ private SubscriptionStrategyEvaluator mySubscriptionStrategyEvaluator;
+ @Autowired
+ private FhirContext myFhirContext;
+
+ @Hook(Pointcut.STORAGE_PRESTORAGE_RESOURCE_CREATED)
+ public void resourcePreCreate(IBaseResource theResource) {
+ validateSubmittedSubscription(theResource);
+ }
+
+ @Hook(Pointcut.STORAGE_PRESTORAGE_RESOURCE_UPDATED)
+ public void resourcePreCreate(IBaseResource theOldResource, IBaseResource theResource) {
+ validateSubmittedSubscription(theResource);
+ }
+
+ public void validateSubmittedSubscription(IBaseResource theSubscription) {
+ if (!"Subscription".equals(myFhirContext.getResourceDefinition(theSubscription).getName())) {
+ return;
+ }
+
+ CanonicalSubscription subscription = mySubscriptionCanonicalizer.canonicalize(theSubscription);
+ boolean finished = false;
+ if (subscription.getStatus() == null) {
+ throw new UnprocessableEntityException("Can not process submitted Subscription - Subscription.status must be populated on this server");
+ }
+
+ switch (subscription.getStatus()) {
+ case REQUESTED:
+ case ACTIVE:
+ break;
+ case ERROR:
+ case OFF:
+ case NULL:
+ finished = true;
+ break;
+ }
+
+ mySubscriptionCanonicalizer.setMatchingStrategyTag(theSubscription, null);
+
+ if (!finished) {
+
+ String query = subscription.getCriteriaString();
+ if (isBlank(query)) {
+ throw new UnprocessableEntityException("Subscription.criteria must be populated");
+ }
+
+ int sep = query.indexOf('?');
+ if (sep <= 1) {
+ throw new UnprocessableEntityException("Subscription.criteria must be in the form \"{Resource Type}?[params]\"");
+ }
+
+ String resType = query.substring(0, sep);
+ if (resType.contains("/")) {
+ throw new UnprocessableEntityException("Subscription.criteria must be in the form \"{Resource Type}?[params]\"");
+ }
+
+ if (subscription.getChannelType() == null) {
+ throw new UnprocessableEntityException("Subscription.channel.type must be populated");
+ } else if (subscription.getChannelType() == CanonicalSubscriptionChannelType.RESTHOOK) {
+ validateChannelPayload(subscription);
+ validateChannelEndpoint(subscription);
+ }
+
+ if (!myDaoRegistry.isResourceTypeSupported(resType)) {
+ throw new UnprocessableEntityException("Subscription.criteria contains invalid/unsupported resource type: " + resType);
+ }
+
+ try {
+ SubscriptionMatchingStrategy strategy = mySubscriptionStrategyEvaluator.determineStrategy(query);
+ mySubscriptionCanonicalizer.setMatchingStrategyTag(theSubscription, strategy);
+ } catch (InvalidRequestException | DataFormatException e) {
+ throw new UnprocessableEntityException("Invalid subscription criteria submitted: " + query + " " + e.getMessage());
+ }
+
+ if (subscription.getChannelType() == null) {
+ throw new UnprocessableEntityException("Subscription.channel.type must be populated on this server");
+ }
+
+ }
+ }
+
+ @SuppressWarnings("WeakerAccess")
+ protected void validateChannelEndpoint(CanonicalSubscription theResource) {
+ if (isBlank(theResource.getEndpointUrl())) {
+ throw new UnprocessableEntityException("Rest-hook subscriptions must have Subscription.channel.endpoint defined");
+ }
+ }
+
+ @SuppressWarnings("WeakerAccess")
+ protected void validateChannelPayload(CanonicalSubscription theResource) {
+ if (!isBlank(theResource.getPayloadString()) && EncodingEnum.forContentType(theResource.getPayloadString()) == null) {
+ throw new UnprocessableEntityException("Invalid value for Subscription.channel.payload: " + theResource.getPayloadString());
+ }
+ }
+
+ @SuppressWarnings("WeakerAccess")
+ @VisibleForTesting
+ public void setSubscriptionCanonicalizerForUnitTest(SubscriptionCanonicalizer theSubscriptionCanonicalizer) {
+ mySubscriptionCanonicalizer = theSubscriptionCanonicalizer;
+ }
+
+ @SuppressWarnings("WeakerAccess")
+ @VisibleForTesting
+ public void setDaoRegistryForUnitTest(DaoRegistry theDaoRegistry) {
+ myDaoRegistry = theDaoRegistry;
+ }
+
+
+ @VisibleForTesting
+ @SuppressWarnings("WeakerAccess")
+ public void setSubscriptionStrategyEvaluatorForUnitTest(SubscriptionStrategyEvaluator theSubscriptionStrategyEvaluator) {
+ mySubscriptionStrategyEvaluator = theSubscriptionStrategyEvaluator;
+ }
+
+}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/ISubscriptionTriggeringSvc.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/triggering/ISubscriptionTriggeringSvc.java
similarity index 95%
rename from hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/ISubscriptionTriggeringSvc.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/triggering/ISubscriptionTriggeringSvc.java
index 3fdbfd869a0..ac972e543f6 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/ISubscriptionTriggeringSvc.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/triggering/ISubscriptionTriggeringSvc.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription;
+package ca.uhn.fhir.jpa.subscription.triggering;
/*-
* #%L
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionTriggeringSvcImpl.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/triggering/SubscriptionTriggeringSvcImpl.java
similarity index 96%
rename from hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionTriggeringSvcImpl.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/triggering/SubscriptionTriggeringSvcImpl.java
index 49506449095..721fe15e588 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionTriggeringSvcImpl.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/triggering/SubscriptionTriggeringSvcImpl.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription;
+package ca.uhn.fhir.jpa.subscription.triggering;
/*-
* #%L
@@ -22,18 +22,18 @@ package ca.uhn.fhir.jpa.subscription;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
-import ca.uhn.fhir.jpa.dao.DaoConfig;
-import ca.uhn.fhir.jpa.dao.DaoRegistry;
-import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
+import ca.uhn.fhir.jpa.api.config.DaoConfig;
+import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
+import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
+import ca.uhn.fhir.jpa.api.svc.ISearchCoordinatorSvc;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.model.sched.HapiJob;
import ca.uhn.fhir.jpa.model.sched.ISchedulerService;
import ca.uhn.fhir.jpa.model.sched.ScheduledJobDefinition;
-import ca.uhn.fhir.jpa.provider.SubscriptionTriggeringProvider;
-import ca.uhn.fhir.jpa.search.ISearchCoordinatorSvc;
import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
-import ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage;
+import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage;
+import ca.uhn.fhir.jpa.subscription.process.matcher.matching.IResourceModifiedConsumer;
import ca.uhn.fhir.model.dstu2.valueset.ResourceTypeEnum;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.api.CacheControlDirective;
@@ -59,7 +59,6 @@ import org.quartz.JobExecutionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
@@ -75,13 +74,12 @@ import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
-import static ca.uhn.fhir.jpa.provider.SubscriptionTriggeringProvider.RESOURCE_ID;
+import static ca.uhn.fhir.jpa.model.util.JpaConstants.SUBSCRIPTION_TRIGGERING_PARAM_RESOURCE_ID;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
-@Service
public class SubscriptionTriggeringSvcImpl implements ISubscriptionTriggeringSvc {
- private static final Logger ourLog = LoggerFactory.getLogger(SubscriptionTriggeringProvider.class);
+ private static final Logger ourLog = LoggerFactory.getLogger(SubscriptionTriggeringSvcImpl.class);
private static final int DEFAULT_MAX_SUBMIT = 10000;
private final List myActiveJobs = new ArrayList<>();
@Autowired
@@ -129,8 +127,8 @@ public class SubscriptionTriggeringSvcImpl implements ISubscriptionTriggeringSvc
// Resource URLs must be compete
for (IPrimitiveType next : resourceIds) {
IdType resourceId = new IdType(next.getValue());
- ValidateUtil.isTrueOrThrowInvalidRequest(resourceId.hasResourceType(), RESOURCE_ID + " parameter must have resource type");
- ValidateUtil.isTrueOrThrowInvalidRequest(resourceId.hasIdPart(), RESOURCE_ID + " parameter must have resource ID part");
+ ValidateUtil.isTrueOrThrowInvalidRequest(resourceId.hasResourceType(), SUBSCRIPTION_TRIGGERING_PARAM_RESOURCE_ID + " parameter must have resource type");
+ ValidateUtil.isTrueOrThrowInvalidRequest(resourceId.hasIdPart(), SUBSCRIPTION_TRIGGERING_PARAM_RESOURCE_ID + " parameter must have resource ID part");
}
// Search URLs must be valid
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/interceptor/SubscriptionDebugLogInterceptor.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/util/SubscriptionDebugLogInterceptor.java
similarity index 94%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/interceptor/SubscriptionDebugLogInterceptor.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/util/SubscriptionDebugLogInterceptor.java
index 4baef540493..288ad03b2d5 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/module/interceptor/SubscriptionDebugLogInterceptor.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/util/SubscriptionDebugLogInterceptor.java
@@ -1,4 +1,4 @@
-package ca.uhn.fhir.jpa.subscription.module.interceptor;
+package ca.uhn.fhir.jpa.subscription.util;
/*-
* #%L
@@ -24,9 +24,9 @@ import ca.uhn.fhir.interceptor.api.Hook;
import ca.uhn.fhir.interceptor.api.Interceptor;
import ca.uhn.fhir.interceptor.api.Pointcut;
import ca.uhn.fhir.jpa.searchparam.matcher.InMemoryMatchResult;
-import ca.uhn.fhir.jpa.subscription.module.CanonicalSubscriptionChannelType;
-import ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage;
-import ca.uhn.fhir.jpa.subscription.module.subscriber.ResourceDeliveryMessage;
+import ca.uhn.fhir.jpa.subscription.model.CanonicalSubscriptionChannelType;
+import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage;
+import ca.uhn.fhir.jpa.subscription.model.ResourceDeliveryMessage;
import ca.uhn.fhir.util.StopWatch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -43,7 +43,7 @@ import java.util.function.Function;
* This interceptor loges each step in the processing pipeline with a
* different event code, using the event codes itemized in
* {@link EventCodeEnum}. By default these are each placed in a logger with
- * a different name (e.g. ca.uhn.fhir.jpa.subscription.module.interceptor.SubscriptionDebugLogInterceptor.SUBS20
+ * a different name (e.g. ca.uhn.fhir.jpa.subscription.util.SubscriptionDebugLogInterceptor.SUBS20
* in order to facilitate fine-grained logging controls where some codes are omitted and
* some are not.
*
* https://chat.fhir.org/#narrow/stream/implementers/topic/Unsupported.20search.20parameters
*/
@Bean
public IServerInterceptor holyFooCowInterceptor() {
return new HolyFooCowInterceptor();
}
-
+
/**
* Do some fancy logging to create a nice access log that has details about each incoming request.
*/
@@ -60,7 +69,7 @@ public class CommonConfig {
return retVal;
}
- public static boolean isLocalTestMode(){
+ public static boolean isLocalTestMode() {
return "true".equalsIgnoreCase(System.getProperty("testmode.local"));
}
From 7c6024fa14576d8a3a953d6eac8b877d6ed549b0 Mon Sep 17 00:00:00 2001
From: jamesagnew
Date: Fri, 3 Apr 2020 07:43:21 -0400
Subject: [PATCH 05/20] More work on subscriptions
---
hapi-fhir-dist/pom.xml | 1 -
.../ca/uhn/fhir/jpa/api/config/DaoConfig.java | 2 +-
.../ca/uhn/fhir/jpa/api/dao/DaoRegistry.java | 2 +-
.../java/ca/uhn/fhir/jpa/api/dao/IDao.java | 2 +-
.../fhir/jpa/api/dao/IFhirResourceDao.java | 2 +-
.../api/dao/IFhirResourceDaoCodeSystem.java | 2 +-
.../api/dao/IFhirResourceDaoComposition.java | 2 +-
.../api/dao/IFhirResourceDaoConceptMap.java | 2 +-
.../api/dao/IFhirResourceDaoEncounter.java | 2 +-
.../dao/IFhirResourceDaoMessageHeader.java | 2 +-
.../jpa/api/dao/IFhirResourceDaoPatient.java | 2 +-
.../dao/IFhirResourceDaoSearchParameter.java | 2 +-
.../IFhirResourceDaoStructureDefinition.java | 2 +-
.../api/dao/IFhirResourceDaoSubscription.java | 2 +-
.../jpa/api/dao/IFhirResourceDaoValueSet.java | 2 +-
.../uhn/fhir/jpa/api/dao/IFhirSystemDao.java | 2 +-
.../java/ca/uhn/fhir/jpa/api/dao/IJpaDao.java | 2 +-
.../dao/MetadataKeyCurrentlyReindexing.java | 2 +-
.../jpa/api/dao/MetadataKeyResourcePid.java | 2 +-
.../fhir/jpa/api/model/DaoMethodOutcome.java | 2 +-
.../fhir/jpa/api/model/DeleteConflict.java | 2 +-
.../jpa/api/model/DeleteConflictList.java | 2 +-
.../jpa/api/model/DeleteMethodOutcome.java | 2 +-
.../fhir/jpa/api/model/ExpungeOptions.java | 2 +-
.../fhir/jpa/api/model/ExpungeOutcome.java | 2 +-
.../fhir/jpa/api/model/TranslationMatch.java | 2 +-
.../fhir/jpa/api/model/TranslationQuery.java | 2 +-
.../jpa/api/model/TranslationRequest.java | 2 +-
.../fhir/jpa/api/model/TranslationResult.java | 2 +-
.../fhir/jpa/api/model/WarmCacheEntry.java | 2 +-
.../jpa/api/svc/ISearchCoordinatorSvc.java | 2 +-
.../ca/uhn/fhir/jpa/config/BaseConfig.java | 15 +++---
.../uhn/fhir/jpa/config/BaseDstu2Config.java | 5 --
.../jpa/config/dstu3/BaseDstu3Config.java | 5 --
.../uhn/fhir/jpa/config/r4/BaseR4Config.java | 5 --
.../uhn/fhir/jpa/config/r5/BaseR5Config.java | 5 --
.../search/PersistedJpaBundleProvider.java | 2 +-
.../PersistedJpaBundleProviderFactory.java | 20 ++++++++
.../fhir/jpa/searchparam/MatchUrlService.java | 1 -
.../searchparam/config/SearchParamConfig.java | 46 ++++++++++++++++++-
.../extractor/ResourceLinkExtractor.java | 1 -
.../SearchParamExtractorService.java | 2 -
.../matcher/InMemoryResourceMatcher.java | 1 -
.../matcher/IndexedSearchParamExtractor.java | 1 -
.../matcher/InlineResourceLinkResolver.java | 1 -
.../matcher/SearchParamMatcher.java | 1 -
.../config/SubscriptionChannelConfig.java | 20 ++++++++
.../config/SubscriptionProcessorConfig.java | 28 +++++++++++
.../process/deliver/DaoResourceRetriever.java | 2 +-
...SubscriptionDeliveringEmailSubscriber.java | 1 -
...scriptionDeliveringRestHookSubscriber.java | 8 +++-
...mpositeInMemoryDaoSubscriptionMatcher.java | 2 +-
.../matching/DaoSubscriptionMatcher.java | 2 +-
.../matching/IResourceModifiedConsumer.java | 2 +-
...aseSubscriberForSubscriptionResources.java | 20 ++++++++
.../SubscriptionActivatingSubscriber.java | 2 +-
.../SubscriptionRegisteringSubscriber.java | 2 +-
.../registry/DaoSubscriptionProvider.java | 2 +-
.../config/SubscriptionSubmitterConfig.java | 20 ++++++++
.../interceptor/SubmitInterceptorLoader.java | 2 +-
.../SubscriptionMatcherInterceptor.java | 2 +-
.../SubscriptionValidatingInterceptor.java | 20 ++++++++
.../ISubscriptionTriggeringSvc.java | 2 +-
.../SubscriptionTriggeringSvcImpl.java | 2 +-
.../autoconfigure/FhirAutoConfiguration.java | 10 ++++
65 files changed, 240 insertions(+), 81 deletions(-)
diff --git a/hapi-fhir-dist/pom.xml b/hapi-fhir-dist/pom.xml
index 872836b3024..2496d5582e6 100644
--- a/hapi-fhir-dist/pom.xml
+++ b/hapi-fhir-dist/pom.xml
@@ -271,7 +271,6 @@
false${project.basedir}/src/assembly/hapi-fhir-standard-distribution.xml
- ${project.basedir}/src/assembly/hapi-fhir-jpaserver-example.xml${project.basedir}/src/assembly/hapi-fhir-android-distribution.xml${project.basedir}/src/assembly/hapi-fhir-cli.xml
diff --git a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/config/DaoConfig.java b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/config/DaoConfig.java
index d0d877dd346..ae9f47c6c3e 100644
--- a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/config/DaoConfig.java
+++ b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/config/DaoConfig.java
@@ -23,7 +23,7 @@ import java.util.TreeSet;
/*
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR JPA API
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/DaoRegistry.java b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/DaoRegistry.java
index d8c3b245039..1a0e12bb6e8 100644
--- a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/DaoRegistry.java
+++ b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/DaoRegistry.java
@@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.api.dao;
/*-
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR JPA API
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IDao.java b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IDao.java
index c4a108425ce..f341f294426 100644
--- a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IDao.java
+++ b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IDao.java
@@ -10,7 +10,7 @@ import java.util.Collection;
/*
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR JPA API
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDao.java b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDao.java
index f550922133a..f6893a810e0 100644
--- a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDao.java
+++ b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDao.java
@@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.api.dao;
/*
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR JPA API
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoCodeSystem.java b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoCodeSystem.java
index 7279a604f8a..ba957e00542 100644
--- a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoCodeSystem.java
+++ b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoCodeSystem.java
@@ -15,7 +15,7 @@ import java.util.List;
/*
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR JPA API
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoComposition.java b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoComposition.java
index 88b353ae90c..cabe7d62ef0 100644
--- a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoComposition.java
+++ b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoComposition.java
@@ -12,7 +12,7 @@ import javax.servlet.http.HttpServletRequest;
/*
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR JPA API
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoConceptMap.java b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoConceptMap.java
index bf2642f162c..04f7f53dfad 100644
--- a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoConceptMap.java
+++ b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoConceptMap.java
@@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.api.dao;
/*
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR JPA API
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoEncounter.java b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoEncounter.java
index 10721239479..b94396b1495 100644
--- a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoEncounter.java
+++ b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoEncounter.java
@@ -4,7 +4,7 @@ import javax.servlet.http.HttpServletRequest;
/*
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR JPA API
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoMessageHeader.java b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoMessageHeader.java
index ebb834adee0..691fd063459 100644
--- a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoMessageHeader.java
+++ b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoMessageHeader.java
@@ -4,7 +4,7 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
/*
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR JPA API
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoPatient.java b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoPatient.java
index 5d1d39d1f34..57fbe535d24 100644
--- a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoPatient.java
+++ b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoPatient.java
@@ -13,7 +13,7 @@ import javax.servlet.http.HttpServletRequest;
/*
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR JPA API
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoSearchParameter.java b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoSearchParameter.java
index afe13c6cf9c..a8d3f12e55b 100644
--- a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoSearchParameter.java
+++ b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoSearchParameter.java
@@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.api.dao;
/*
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR JPA API
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoStructureDefinition.java b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoStructureDefinition.java
index da3cb9022c0..7864e3310cb 100644
--- a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoStructureDefinition.java
+++ b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoStructureDefinition.java
@@ -4,7 +4,7 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
/*
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR JPA API
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoSubscription.java b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoSubscription.java
index 9baebbf7b63..f2f94f30b82 100644
--- a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoSubscription.java
+++ b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoSubscription.java
@@ -6,7 +6,7 @@ import org.hl7.fhir.instance.model.api.IIdType;
/*
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR JPA API
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoValueSet.java b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoValueSet.java
index c37c9201cc8..fa30e3576de 100644
--- a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoValueSet.java
+++ b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirResourceDaoValueSet.java
@@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.api.dao;
/*
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR JPA API
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirSystemDao.java b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirSystemDao.java
index c48bfebd110..b1d43426689 100644
--- a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirSystemDao.java
+++ b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IFhirSystemDao.java
@@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.api.dao;
/*
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR JPA API
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IJpaDao.java b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IJpaDao.java
index 5824cbf141e..f9ac5d9bd10 100644
--- a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IJpaDao.java
+++ b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/IJpaDao.java
@@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.api.dao;
/*-
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR JPA API
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/MetadataKeyCurrentlyReindexing.java b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/MetadataKeyCurrentlyReindexing.java
index 071e29fa2c6..c5778090d84 100644
--- a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/MetadataKeyCurrentlyReindexing.java
+++ b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/MetadataKeyCurrentlyReindexing.java
@@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.api.dao;
/*-
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR JPA API
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/MetadataKeyResourcePid.java b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/MetadataKeyResourcePid.java
index e90a4b8edcc..4c39cad0785 100644
--- a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/MetadataKeyResourcePid.java
+++ b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/MetadataKeyResourcePid.java
@@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.api.dao;
/*-
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR JPA API
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/DaoMethodOutcome.java b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/DaoMethodOutcome.java
index 52a8c823fc4..4a9247efb38 100644
--- a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/DaoMethodOutcome.java
+++ b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/DaoMethodOutcome.java
@@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.api.model;
/*
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR JPA API
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/DeleteConflict.java b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/DeleteConflict.java
index dc0c6eccb1a..b53bcd46004 100644
--- a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/DeleteConflict.java
+++ b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/DeleteConflict.java
@@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.api.model;
/*
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR JPA API
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/DeleteConflictList.java b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/DeleteConflictList.java
index 792e586eebd..6aaf63547de 100644
--- a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/DeleteConflictList.java
+++ b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/DeleteConflictList.java
@@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.api.model;
/*-
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR JPA API
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/DeleteMethodOutcome.java b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/DeleteMethodOutcome.java
index 9f140cb1a72..e1ab49e8263 100644
--- a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/DeleteMethodOutcome.java
+++ b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/DeleteMethodOutcome.java
@@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.api.model;
/*
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR JPA API
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/ExpungeOptions.java b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/ExpungeOptions.java
index a3ec0576961..162fd114658 100644
--- a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/ExpungeOptions.java
+++ b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/ExpungeOptions.java
@@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.api.model;
/*-
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR JPA API
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/ExpungeOutcome.java b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/ExpungeOutcome.java
index 05e56610a4d..757a2ecf335 100644
--- a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/ExpungeOutcome.java
+++ b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/ExpungeOutcome.java
@@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.api.model;
/*-
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR JPA API
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/TranslationMatch.java b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/TranslationMatch.java
index d6f7a5cbd07..a52421a0916 100644
--- a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/TranslationMatch.java
+++ b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/TranslationMatch.java
@@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.api.model;
/*
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR JPA API
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/TranslationQuery.java b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/TranslationQuery.java
index 4e8569a4276..6aefcf9ae3a 100644
--- a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/TranslationQuery.java
+++ b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/TranslationQuery.java
@@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.api.model;
/*
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR JPA API
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/TranslationRequest.java b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/TranslationRequest.java
index 752b4fcfeee..19d6388b96c 100644
--- a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/TranslationRequest.java
+++ b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/TranslationRequest.java
@@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.api.model;
/*
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR JPA API
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/TranslationResult.java b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/TranslationResult.java
index 7744e47cd07..8e305b241ad 100644
--- a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/TranslationResult.java
+++ b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/TranslationResult.java
@@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.api.model;
/*
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR JPA API
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/WarmCacheEntry.java b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/WarmCacheEntry.java
index a5401a86e9e..81411ac4cf8 100644
--- a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/WarmCacheEntry.java
+++ b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/model/WarmCacheEntry.java
@@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.api.model;
/*-
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR JPA API
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/svc/ISearchCoordinatorSvc.java b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/svc/ISearchCoordinatorSvc.java
index ebfcd3f0830..b9f38397ff3 100644
--- a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/svc/ISearchCoordinatorSvc.java
+++ b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/svc/ISearchCoordinatorSvc.java
@@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.api.svc;
/*-
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR JPA API
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/BaseConfig.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/BaseConfig.java
index 82182d21b3e..af01c6165ae 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/BaseConfig.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/BaseConfig.java
@@ -32,6 +32,7 @@ import ca.uhn.fhir.jpa.search.cache.ISearchCacheSvc;
import ca.uhn.fhir.jpa.search.cache.ISearchResultCacheSvc;
import ca.uhn.fhir.jpa.search.reindex.IResourceReindexingSvc;
import ca.uhn.fhir.jpa.search.reindex.ResourceReindexingSvcImpl;
+import ca.uhn.fhir.jpa.searchparam.config.SearchParamConfig;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
import ca.uhn.fhir.jpa.searchparam.registry.SearchParamRegistryImpl;
import ca.uhn.fhir.rest.api.server.RequestDetails;
@@ -43,6 +44,7 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
+import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.core.env.Environment;
@@ -83,7 +85,12 @@ import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = WebSocketConfigurer.class),
@ComponentScan.Filter(type = FilterType.REGEX, pattern = ".*\\.test\\..*"),
@ComponentScan.Filter(type = FilterType.REGEX, pattern = ".*Test.*"),
- @ComponentScan.Filter(type = FilterType.REGEX, pattern = "ca.uhn.fhir.jpa.subscription.module.standalone.*")})
+ @ComponentScan.Filter(type = FilterType.REGEX, pattern = "ca.uhn.fhir.jpa.subscription.*"),
+ @ComponentScan.Filter(type = FilterType.REGEX, pattern = "ca.uhn.fhir.jpa.searchparam.*")
+})
+@Import({
+ SearchParamConfig.class
+})
public abstract class BaseConfig {
public static final String JPA_VALIDATION_SUPPORT_CHAIN = "myJpaValidationSupportChain";
@@ -133,12 +140,6 @@ public abstract class BaseConfig {
return b;
}
- @Bean
- public ISearchParamRegistry searchParamRegistry() {
- return new SearchParamRegistryImpl();
- }
-
-
@Bean(name = "mySubscriptionTriggeringProvider")
@Lazy
public SubscriptionTriggeringProvider subscriptionTriggeringProvider() {
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/BaseDstu2Config.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/BaseDstu2Config.java
index 2814ddb95d0..8e85e7e02ab 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/BaseDstu2Config.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/BaseDstu2Config.java
@@ -124,11 +124,6 @@ public class BaseDstu2Config extends BaseConfig {
return searchDao;
}
- @Bean(autowire = Autowire.BY_TYPE)
- public SearchParamExtractorDstu2 searchParamExtractor() {
- return new SearchParamExtractorDstu2();
- }
-
@Bean(name = "mySystemDaoDstu2", autowire = Autowire.BY_NAME)
public IFhirSystemDao systemDaoDstu2() {
ca.uhn.fhir.jpa.dao.FhirSystemDaoDstu2 retVal = new ca.uhn.fhir.jpa.dao.FhirSystemDaoDstu2();
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/dstu3/BaseDstu3Config.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/dstu3/BaseDstu3Config.java
index a2106cd7d99..13e19195641 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/dstu3/BaseDstu3Config.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/dstu3/BaseDstu3Config.java
@@ -101,11 +101,6 @@ public class BaseDstu3Config extends BaseConfigDstu3Plus {
return new FulltextSearchSvcImpl();
}
- @Bean
- public SearchParamExtractorDstu3 searchParamExtractor() {
- return new SearchParamExtractorDstu3();
- }
-
@Bean(name = "mySystemDaoDstu3")
public IFhirSystemDao systemDaoDstu3() {
return new ca.uhn.fhir.jpa.dao.dstu3.FhirSystemDaoDstu3();
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/r4/BaseR4Config.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/r4/BaseR4Config.java
index e2bf083d923..bf53a64685f 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/r4/BaseR4Config.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/r4/BaseR4Config.java
@@ -103,11 +103,6 @@ public class BaseR4Config extends BaseConfigDstu3Plus {
return searchDao;
}
- @Bean(autowire = Autowire.BY_TYPE)
- public SearchParamExtractorR4 searchParamExtractor() {
- return new SearchParamExtractorR4();
- }
-
@Bean(name = "mySystemDaoR4", autowire = Autowire.BY_NAME)
public IFhirSystemDao systemDaoR4() {
ca.uhn.fhir.jpa.dao.r4.FhirSystemDaoR4 retVal = new ca.uhn.fhir.jpa.dao.r4.FhirSystemDaoR4();
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/r5/BaseR5Config.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/r5/BaseR5Config.java
index 3d694551dcc..78b6327e92d 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/r5/BaseR5Config.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/r5/BaseR5Config.java
@@ -103,11 +103,6 @@ public class BaseR5Config extends BaseConfigDstu3Plus {
return searchDao;
}
- @Bean(autowire = Autowire.BY_TYPE)
- public SearchParamExtractorR5 searchParamExtractor() {
- return new SearchParamExtractorR5();
- }
-
@Bean(name = "mySystemDaoR5", autowire = Autowire.BY_NAME)
public IFhirSystemDao systemDaoR5() {
ca.uhn.fhir.jpa.dao.r5.FhirSystemDaoR5 retVal = new ca.uhn.fhir.jpa.dao.r5.FhirSystemDaoR5();
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/PersistedJpaBundleProvider.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/PersistedJpaBundleProvider.java
index c011678ea41..ac5e0e6932e 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/PersistedJpaBundleProvider.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/PersistedJpaBundleProvider.java
@@ -96,6 +96,7 @@ public class PersistedJpaBundleProvider implements IBundleProvider {
@Autowired
private ISearchCoordinatorSvc mySearchCoordinatorSvc;
@Autowired
+ private ISearchCacheSvc mySearchCacheSvc;
/*
* Non autowired fields (will be different for every instance
@@ -103,7 +104,6 @@ public class PersistedJpaBundleProvider implements IBundleProvider {
*/
private final RequestDetails myRequest;
- private ISearchCacheSvc mySearchCacheSvc;
private Search mySearchEntity;
private String myUuid;
private boolean myCacheHit;
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/PersistedJpaBundleProviderFactory.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/PersistedJpaBundleProviderFactory.java
index 5432865e99f..3c695cd0b12 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/PersistedJpaBundleProviderFactory.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/PersistedJpaBundleProviderFactory.java
@@ -1,5 +1,25 @@
package ca.uhn.fhir.jpa.search;
+/*-
+ * #%L
+ * HAPI FHIR JPA Server
+ * %%
+ * Copyright (C) 2014 - 2020 University Health Network
+ * %%
+ * 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%
+ */
+
import ca.uhn.fhir.jpa.config.BaseConfig;
import ca.uhn.fhir.jpa.dao.ISearchBuilder;
import ca.uhn.fhir.jpa.entity.Search;
diff --git a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/MatchUrlService.java b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/MatchUrlService.java
index fb77ea8af24..7b4e98ae21e 100644
--- a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/MatchUrlService.java
+++ b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/MatchUrlService.java
@@ -44,7 +44,6 @@ import java.util.List;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
-@Service
public class MatchUrlService {
@Autowired
diff --git a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/config/SearchParamConfig.java b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/config/SearchParamConfig.java
index dc937e0f6fc..008a5e535ee 100644
--- a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/config/SearchParamConfig.java
+++ b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/config/SearchParamConfig.java
@@ -21,22 +21,30 @@ package ca.uhn.fhir.jpa.searchparam.config;
*/
import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
+import ca.uhn.fhir.jpa.searchparam.extractor.IResourceLinkResolver;
import ca.uhn.fhir.jpa.searchparam.extractor.ISearchParamExtractor;
+import ca.uhn.fhir.jpa.searchparam.extractor.ResourceLinkExtractor;
import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorDstu2;
import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorDstu3;
import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorR4;
import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorR5;
+import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorService;
+import ca.uhn.fhir.jpa.searchparam.matcher.InMemoryResourceMatcher;
+import ca.uhn.fhir.jpa.searchparam.matcher.IndexedSearchParamExtractor;
+import ca.uhn.fhir.jpa.searchparam.matcher.InlineResourceLinkResolver;
+import ca.uhn.fhir.jpa.searchparam.matcher.SearchParamMatcher;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
import ca.uhn.fhir.jpa.searchparam.registry.SearchParamRegistryImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.EnableScheduling;
@Configuration
@EnableScheduling
-@ComponentScan(basePackages = {"ca.uhn.fhir.jpa.searchparam"})
public class SearchParamConfig {
@Autowired
@@ -66,4 +74,40 @@ public class SearchParamConfig {
return new SearchParamRegistryImpl();
}
+ @Bean
+ public MatchUrlService matchUrlService() {
+ return new MatchUrlService();
+ }
+
+ @Bean
+ public ResourceLinkExtractor resourceLinkExtractor() {
+ return new ResourceLinkExtractor();
+ }
+
+ @Bean
+ @Lazy
+ public SearchParamExtractorService searchParamExtractorService(){
+ return new SearchParamExtractorService();
+ }
+
+ @Bean
+ public IndexedSearchParamExtractor indexedSearchParamExtractor() {
+ return new IndexedSearchParamExtractor();
+ }
+
+ @Bean
+ public InlineResourceLinkResolver inlineResourceLinkResolver() {
+ return new InlineResourceLinkResolver();
+ }
+
+ @Bean
+ public InMemoryResourceMatcher InMemoryResourceMatcher() {
+ return new InMemoryResourceMatcher();
+ }
+
+ @Bean
+ public SearchParamMatcher SearchParamMatcher() {
+ return new SearchParamMatcher();
+ }
+
}
diff --git a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/ResourceLinkExtractor.java b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/ResourceLinkExtractor.java
index 89e4e2d5d46..16b8f98ecb2 100644
--- a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/ResourceLinkExtractor.java
+++ b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/ResourceLinkExtractor.java
@@ -46,7 +46,6 @@ import java.util.Map;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
-@Service
public class ResourceLinkExtractor {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceLinkExtractor.class);
diff --git a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/SearchParamExtractorService.java b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/SearchParamExtractorService.java
index 95ce06c08de..42545f90caf 100644
--- a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/SearchParamExtractorService.java
+++ b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/extractor/SearchParamExtractorService.java
@@ -36,8 +36,6 @@ import org.springframework.stereotype.Service;
import java.util.Collection;
-@Service
-@Lazy
public class SearchParamExtractorService {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SearchParamExtractorService.class);
diff --git a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/matcher/InMemoryResourceMatcher.java b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/matcher/InMemoryResourceMatcher.java
index 85d2281c30f..63a86594f98 100644
--- a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/matcher/InMemoryResourceMatcher.java
+++ b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/matcher/InMemoryResourceMatcher.java
@@ -50,7 +50,6 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
-@Service
public class InMemoryResourceMatcher {
@Autowired
diff --git a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/matcher/IndexedSearchParamExtractor.java b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/matcher/IndexedSearchParamExtractor.java
index cc0fb9da79a..5d1afa98b95 100644
--- a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/matcher/IndexedSearchParamExtractor.java
+++ b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/matcher/IndexedSearchParamExtractor.java
@@ -30,7 +30,6 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
-@Service
public class IndexedSearchParamExtractor {
@Autowired
private FhirContext myContext;
diff --git a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/matcher/InlineResourceLinkResolver.java b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/matcher/InlineResourceLinkResolver.java
index 9c19daa9365..9de028b7f57 100644
--- a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/matcher/InlineResourceLinkResolver.java
+++ b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/matcher/InlineResourceLinkResolver.java
@@ -31,7 +31,6 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.springframework.stereotype.Service;
-@Service
public class InlineResourceLinkResolver implements IResourceLinkResolver {
@Override
diff --git a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/matcher/SearchParamMatcher.java b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/matcher/SearchParamMatcher.java
index 4266f361cb7..56fc2bb41b4 100644
--- a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/matcher/SearchParamMatcher.java
+++ b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/matcher/SearchParamMatcher.java
@@ -26,7 +26,6 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
-@Service
public class SearchParamMatcher {
@Autowired
private IndexedSearchParamExtractor myIndexedSearchParamExtractor;
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/config/SubscriptionChannelConfig.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/config/SubscriptionChannelConfig.java
index a9408ddc681..64d9c62d8a9 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/config/SubscriptionChannelConfig.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/config/SubscriptionChannelConfig.java
@@ -1,5 +1,25 @@
package ca.uhn.fhir.jpa.subscription.channel.config;
+/*-
+ * #%L
+ * HAPI FHIR Subscription Server
+ * %%
+ * Copyright (C) 2014 - 2020 University Health Network
+ * %%
+ * 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%
+ */
+
import ca.uhn.fhir.jpa.subscription.channel.queue.IQueueChannelFactory;
import ca.uhn.fhir.jpa.subscription.channel.queue.LinkedBlockingQueueChannelFactory;
import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionChannelFactory;
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/config/SubscriptionProcessorConfig.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/config/SubscriptionProcessorConfig.java
index d923ce00336..88151a43de1 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/config/SubscriptionProcessorConfig.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/config/SubscriptionProcessorConfig.java
@@ -1,11 +1,33 @@
package ca.uhn.fhir.jpa.subscription.process.config;
+/*-
+ * #%L
+ * HAPI FHIR Subscription Server
+ * %%
+ * Copyright (C) 2014 - 2020 University Health Network
+ * %%
+ * 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%
+ */
+
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionChannelRegistry;
import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionDeliveryChannelNamer;
import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionDeliveryHandlerFactory;
import ca.uhn.fhir.jpa.subscription.process.deliver.DaoResourceRetriever;
import ca.uhn.fhir.jpa.subscription.process.deliver.IResourceRetriever;
+import ca.uhn.fhir.jpa.subscription.process.deliver.email.IEmailSender;
+import ca.uhn.fhir.jpa.subscription.process.deliver.email.SubscriptionDeliveringEmailSubscriber;
import ca.uhn.fhir.jpa.subscription.process.deliver.resthook.SubscriptionDeliveringRestHookSubscriber;
import ca.uhn.fhir.jpa.subscription.process.deliver.websocket.WebsocketConnectionValidator;
import ca.uhn.fhir.jpa.subscription.process.matcher.matching.CompositeInMemoryDaoSubscriptionMatcher;
@@ -117,6 +139,12 @@ public class SubscriptionProcessorConfig {
return new SubscriptionDeliveringRestHookSubscriber();
}
+ @Bean
+ @Scope("prototype")
+ public SubscriptionDeliveringEmailSubscriber subscriptionDeliveringEmailSubscriber(IEmailSender theEmailSender) {
+ return new SubscriptionDeliveringEmailSubscriber(theEmailSender);
+ }
+
@Bean
public InMemorySubscriptionMatcher inMemorySubscriptionMatcher() {
return new InMemorySubscriptionMatcher();
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/DaoResourceRetriever.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/DaoResourceRetriever.java
index d070b5adcba..0b7721be732 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/DaoResourceRetriever.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/DaoResourceRetriever.java
@@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.subscription.process.deliver;
/*-
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR Subscription Server
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/email/SubscriptionDeliveringEmailSubscriber.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/email/SubscriptionDeliveringEmailSubscriber.java
index ce650ccad2f..cd4eeab97aa 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/email/SubscriptionDeliveringEmailSubscriber.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/email/SubscriptionDeliveringEmailSubscriber.java
@@ -38,7 +38,6 @@ import java.util.List;
import static org.apache.commons.lang3.StringUtils.*;
-@Component
@Scope("prototype")
public class SubscriptionDeliveringEmailSubscriber extends BaseSubscriptionDeliverySubscriber {
private Logger ourLog = LoggerFactory.getLogger(SubscriptionDeliveringEmailSubscriber.class);
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/resthook/SubscriptionDeliveringRestHookSubscriber.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/resthook/SubscriptionDeliveringRestHookSubscriber.java
index d9514007060..1af1029bd54 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/resthook/SubscriptionDeliveringRestHookSubscriber.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/resthook/SubscriptionDeliveringRestHookSubscriber.java
@@ -48,13 +48,19 @@ import java.util.*;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
-@Component
@Scope("prototype")
public class SubscriptionDeliveringRestHookSubscriber extends BaseSubscriptionDeliverySubscriber {
@Autowired
IResourceRetriever myResourceRetriever;
private Logger ourLog = LoggerFactory.getLogger(SubscriptionDeliveringRestHookSubscriber.class);
+ /**
+ * Constructor
+ */
+ public SubscriptionDeliveringRestHookSubscriber() {
+ super();
+ }
+
protected void deliverPayload(ResourceDeliveryMessage theMsg, CanonicalSubscription theSubscription, EncodingEnum thePayloadType, IGenericClient theClient) {
IBaseResource payloadResource = getAndMassagePayload(theMsg, theSubscription);
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/CompositeInMemoryDaoSubscriptionMatcher.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/CompositeInMemoryDaoSubscriptionMatcher.java
index ae13ef2ad0a..46bd57c02e6 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/CompositeInMemoryDaoSubscriptionMatcher.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/CompositeInMemoryDaoSubscriptionMatcher.java
@@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.subscription.process.matcher.matching;
/*-
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR Subscription Server
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/DaoSubscriptionMatcher.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/DaoSubscriptionMatcher.java
index 8299ca9c8fe..3c9cb3437aa 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/DaoSubscriptionMatcher.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/DaoSubscriptionMatcher.java
@@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.subscription.process.matcher.matching;
/*-
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR Subscription Server
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/IResourceModifiedConsumer.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/IResourceModifiedConsumer.java
index 047649909b3..577dbc4e2fc 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/IResourceModifiedConsumer.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/IResourceModifiedConsumer.java
@@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.subscription.process.matcher.matching;
/*-
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR Subscription Server
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/BaseSubscriberForSubscriptionResources.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/BaseSubscriberForSubscriptionResources.java
index 79e207a281f..f1544848335 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/BaseSubscriberForSubscriptionResources.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/BaseSubscriberForSubscriptionResources.java
@@ -1,5 +1,25 @@
package ca.uhn.fhir.jpa.subscription.process.matcher.subscriber;
+/*-
+ * #%L
+ * HAPI FHIR Subscription Server
+ * %%
+ * Copyright (C) 2014 - 2020 University Health Network
+ * %%
+ * 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%
+ */
+
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage;
import ca.uhn.fhir.model.dstu2.valueset.ResourceTypeEnum;
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionActivatingSubscriber.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionActivatingSubscriber.java
index a1f1dbfb49e..ddc167ee6cd 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionActivatingSubscriber.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionActivatingSubscriber.java
@@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.subscription.process.matcher.subscriber;
/*-
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR Subscription Server
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionRegisteringSubscriber.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionRegisteringSubscriber.java
index 1273ad8e8a8..9c6eabdae79 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionRegisteringSubscriber.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionRegisteringSubscriber.java
@@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.subscription.process.matcher.subscriber;
/*-
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR Subscription Server
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/DaoSubscriptionProvider.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/DaoSubscriptionProvider.java
index ad75c98df8e..adb4b885534 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/DaoSubscriptionProvider.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/DaoSubscriptionProvider.java
@@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.subscription.process.registry;
/*-
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR Subscription Server
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/config/SubscriptionSubmitterConfig.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/config/SubscriptionSubmitterConfig.java
index eab841e50b2..edbb96c5296 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/config/SubscriptionSubmitterConfig.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/config/SubscriptionSubmitterConfig.java
@@ -1,5 +1,25 @@
package ca.uhn.fhir.jpa.subscription.submit.config;
+/*-
+ * #%L
+ * HAPI FHIR Subscription Server
+ * %%
+ * Copyright (C) 2014 - 2020 University Health Network
+ * %%
+ * 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%
+ */
+
import ca.uhn.fhir.jpa.subscription.submit.interceptor.SubscriptionMatcherInterceptor;
import ca.uhn.fhir.jpa.subscription.submit.interceptor.SubmitInterceptorLoader;
import ca.uhn.fhir.jpa.subscription.submit.interceptor.SubscriptionValidatingInterceptor;
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubmitInterceptorLoader.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubmitInterceptorLoader.java
index af3c7030410..c6715a95232 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubmitInterceptorLoader.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubmitInterceptorLoader.java
@@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.subscription.submit.interceptor;
/*-
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR Subscription Server
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionMatcherInterceptor.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionMatcherInterceptor.java
index 2d88a34a5de..ceb3dccf7d9 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionMatcherInterceptor.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionMatcherInterceptor.java
@@ -24,7 +24,7 @@ import javax.annotation.PostConstruct;
/*-
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR Subscription Server
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionValidatingInterceptor.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionValidatingInterceptor.java
index df1157bd96e..237d22a38e6 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionValidatingInterceptor.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionValidatingInterceptor.java
@@ -1,5 +1,25 @@
package ca.uhn.fhir.jpa.subscription.submit.interceptor;
+/*-
+ * #%L
+ * HAPI FHIR Subscription Server
+ * %%
+ * Copyright (C) 2014 - 2020 University Health Network
+ * %%
+ * 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%
+ */
+
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.interceptor.api.Hook;
import ca.uhn.fhir.interceptor.api.Interceptor;
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/triggering/ISubscriptionTriggeringSvc.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/triggering/ISubscriptionTriggeringSvc.java
index ac972e543f6..9a457dc6829 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/triggering/ISubscriptionTriggeringSvc.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/triggering/ISubscriptionTriggeringSvc.java
@@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.subscription.triggering;
/*-
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR Subscription Server
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/triggering/SubscriptionTriggeringSvcImpl.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/triggering/SubscriptionTriggeringSvcImpl.java
index 721fe15e588..5a268329c62 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/triggering/SubscriptionTriggeringSvcImpl.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/triggering/SubscriptionTriggeringSvcImpl.java
@@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.subscription.triggering;
/*-
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR Subscription Server
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/src/main/java/ca/uhn/fhir/spring/boot/autoconfigure/FhirAutoConfiguration.java b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/src/main/java/ca/uhn/fhir/spring/boot/autoconfigure/FhirAutoConfiguration.java
index 1902686f361..e72f835c0bb 100644
--- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/src/main/java/ca/uhn/fhir/spring/boot/autoconfigure/FhirAutoConfiguration.java
+++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure/src/main/java/ca/uhn/fhir/spring/boot/autoconfigure/FhirAutoConfiguration.java
@@ -27,9 +27,13 @@ import ca.uhn.fhir.jpa.config.BaseJavaConfigDstu2;
import ca.uhn.fhir.jpa.config.BaseJavaConfigDstu3;
import ca.uhn.fhir.jpa.config.BaseJavaConfigR4;
import ca.uhn.fhir.jpa.api.config.DaoConfig;
+import ca.uhn.fhir.jpa.config.WebsocketDispatcherConfig;
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
import ca.uhn.fhir.jpa.provider.BaseJpaProvider;
import ca.uhn.fhir.jpa.provider.BaseJpaSystemProvider;
+import ca.uhn.fhir.jpa.subscription.channel.config.SubscriptionChannelConfig;
+import ca.uhn.fhir.jpa.subscription.process.config.SubscriptionProcessorConfig;
+import ca.uhn.fhir.jpa.subscription.submit.config.SubscriptionSubmitterConfig;
import ca.uhn.fhir.okhttp.client.OkHttpRestfulClientFactory;
import ca.uhn.fhir.rest.client.apache.ApacheRestfulClientFactory;
import ca.uhn.fhir.rest.client.api.IClientInterceptor;
@@ -58,6 +62,7 @@ import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.util.CollectionUtils;
@@ -161,6 +166,11 @@ public class FhirAutoConfiguration {
@Configuration
@EntityScan(basePackages = {"ca.uhn.fhir.jpa.entity", "ca.uhn.fhir.jpa.model.entity"})
+ @Import({
+ SubscriptionChannelConfig.class,
+ SubscriptionProcessorConfig.class,
+ SubscriptionSubmitterConfig.class
+ })
static class FhirJpaDaoConfiguration {
@Bean
From 68db40d057b961f4fe3b91b5d6d99227d1922a71 Mon Sep 17 00:00:00 2001
From: jamesagnew
Date: Fri, 3 Apr 2020 08:07:39 -0400
Subject: [PATCH 06/20] Queue factory cleanup
---
.../subscription/SubscriptionChannelFactory.java | 5 +++--
.../subscriber/MatchingQueueSubscriberLoader.java | 3 ++-
.../SubscriptionMatcherInterceptor.java | 14 +++++++++-----
3 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelFactory.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelFactory.java
index b4c18e2bff9..03b5704d650 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelFactory.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelFactory.java
@@ -24,6 +24,7 @@ import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage;
import ca.uhn.fhir.jpa.subscription.channel.queue.IQueueChannelFactory;
import ca.uhn.fhir.jpa.subscription.model.ResourceDeliveryMessage;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.SubscribableChannel;
public class SubscriptionChannelFactory {
@@ -35,8 +36,8 @@ public class SubscriptionChannelFactory {
return mySubscribableChannelFactory.getOrCreateReceiver(theChannelName, ResourceDeliveryMessage.class, mySubscribableChannelFactory.getDeliveryChannelConcurrentConsumers());
}
- public SubscribableChannel newMatchingSendingChannel(String theChannelName) {
- return mySubscribableChannelFactory.getOrCreateReceiver(theChannelName, ResourceModifiedMessage.class, mySubscribableChannelFactory.getMatchingChannelConcurrentConsumers());
+ public MessageChannel newMatchingSendingChannel(String theChannelName) {
+ return mySubscribableChannelFactory.getOrCreateSender(theChannelName, ResourceModifiedMessage.class, mySubscribableChannelFactory.getMatchingChannelConcurrentConsumers());
}
public SubscribableChannel newMatchingReceivingChannel(String theChannelName) {
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/MatchingQueueSubscriberLoader.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/MatchingQueueSubscriberLoader.java
index a4b7d6ef9cf..82202cb777f 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/MatchingQueueSubscriberLoader.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/MatchingQueueSubscriberLoader.java
@@ -10,6 +10,8 @@ import org.springframework.messaging.SubscribableChannel;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
+import static ca.uhn.fhir.jpa.subscription.process.matcher.subscriber.SubscriptionMatchingSubscriber.SUBSCRIPTION_MATCHING_CHANNEL_NAME;
+
/*-
* #%L
* HAPI FHIR Subscription Server
@@ -32,7 +34,6 @@ import javax.annotation.PreDestroy;
public class MatchingQueueSubscriberLoader {
private Logger ourLog = LoggerFactory.getLogger(MatchingQueueSubscriberLoader.class);
- public static final String SUBSCRIPTION_MATCHING_CHANNEL_NAME = "subscription-matching";
@Autowired
private SubscriptionMatchingSubscriber mySubscriptionMatchingSubscriber;
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionMatcherInterceptor.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionMatcherInterceptor.java
index ceb3dccf7d9..d5c2371063b 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionMatcherInterceptor.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionMatcherInterceptor.java
@@ -1,13 +1,17 @@
package ca.uhn.fhir.jpa.subscription.submit.interceptor;
import ca.uhn.fhir.context.FhirContext;
-import ca.uhn.fhir.interceptor.api.*;
+import ca.uhn.fhir.interceptor.api.Hook;
+import ca.uhn.fhir.interceptor.api.HookParams;
+import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
+import ca.uhn.fhir.interceptor.api.Interceptor;
+import ca.uhn.fhir.interceptor.api.Pointcut;
import ca.uhn.fhir.jpa.subscription.channel.queue.LinkedBlockingQueueChannel;
-import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage;
import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionChannelFactory;
+import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedJsonMessage;
+import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage;
import ca.uhn.fhir.jpa.subscription.process.matcher.matching.IResourceModifiedConsumer;
import ca.uhn.fhir.jpa.subscription.process.matcher.subscriber.SubscriptionMatchingSubscriber;
-import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedJsonMessage;
import ca.uhn.fhir.jpa.util.JpaInterceptorBroadcaster;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import com.google.common.annotations.VisibleForTesting;
@@ -16,7 +20,7 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.messaging.SubscribableChannel;
+import org.springframework.messaging.MessageChannel;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;
@@ -54,7 +58,7 @@ public class SubscriptionMatcherInterceptor implements IResourceModifiedConsumer
@Autowired
private SubscriptionChannelFactory mySubscriptionChannelFactory;
- private SubscribableChannel myMatchingChannel;
+ private MessageChannel myMatchingChannel;
/**
* Constructor
From fef447afeebd6a82eb39f5a88939fc616f757f31 Mon Sep 17 00:00:00 2001
From: jamesagnew
Date: Sat, 4 Apr 2020 16:07:01 -0400
Subject: [PATCH 07/20] Work on subscription cleanup
---
.../ca/uhn/fhir/jpa/demo/JpaServerDemo.java | 5 +-
.../ca/uhn/fhir/jpa/api/config/DaoConfig.java | 24 +-----
.../subscription/SubscriptionTestUtil.java | 12 +--
.../fhir/jpa/model/entity/ModelConfig.java | 22 -----
hapi-fhir-jpaserver-subscription/pom.xml | 5 ++
.../channel/queue/IQueueChannelFactory.java | 5 --
.../LinkedBlockingQueueChannelFactory.java | 23 ++---
.../SubscriptionChannelFactory.java | 46 +++++++++-
.../SubscriptionChannelRegistry.java | 6 --
.../model/config/SubscriptionModelConfig.java | 44 ++++++++++
.../config/SubscriptionProcessorConfig.java | 22 +----
.../matching/IResourceModifiedConsumer.java | 12 +++
.../SubscriptionStrategyEvaluator.java | 7 ++
.../SubscriptionActivatingSubscriber.java | 72 ++--------------
.../SubscriptionMatchingSubscriber.java | 7 ++
.../process/registry/SubscriptionLoader.java | 19 ++---
.../config/SubscriptionSubmitterConfig.java | 19 ++++-
.../SubscriptionMatcherInterceptor.java | 28 +++---
... SubscriptionSubmitInterceptorLoader.java} | 36 ++------
.../SubscriptionValidatingInterceptor.java | 17 ++--
.../SubscriptionChannelRegistryTest.java | 2 -
...bscriptionSubmitInterceptorLoaderTest.java | 85 +++++++++++++++++++
.../ca/uhn/fhirtest/TestRestfulServer.java | 8 +-
23 files changed, 293 insertions(+), 233 deletions(-)
create mode 100644 hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/model/config/SubscriptionModelConfig.java
rename hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/{SubmitInterceptorLoader.java => SubscriptionSubmitInterceptorLoader.java} (61%)
create mode 100644 hapi-fhir-jpaserver-subscription/src/test/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionSubmitInterceptorLoaderTest.java
diff --git a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/JpaServerDemo.java b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/JpaServerDemo.java
index 98956b3ba1e..fd471bd9141 100644
--- a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/JpaServerDemo.java
+++ b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/JpaServerDemo.java
@@ -36,7 +36,7 @@ import ca.uhn.fhir.jpa.provider.dstu3.JpaSystemProviderDstu3;
import ca.uhn.fhir.jpa.provider.r4.JpaConformanceProviderR4;
import ca.uhn.fhir.jpa.provider.r4.JpaSystemProviderR4;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
-import ca.uhn.fhir.jpa.subscription.submit.interceptor.SubmitInterceptorLoader;
+import ca.uhn.fhir.jpa.subscription.submit.interceptor.SubscriptionSubmitInterceptorLoader;
import ca.uhn.fhir.jpa.util.ResourceProviderFactory;
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
import ca.uhn.fhir.model.dstu2.resource.Bundle;
@@ -173,9 +173,6 @@ public class JpaServerDemo extends RestfulServer {
daoConfig.setEnforceReferentialIntegrityOnWrite(!ContextHolder.isDisableReferentialIntegrity());
daoConfig.setReuseCachedSearchResultsForMillis(ContextHolder.getReuseCachedSearchResultsForMillis());
- SubmitInterceptorLoader submitInterceptorLoader = myAppCtx.getBean(SubmitInterceptorLoader.class);
- submitInterceptorLoader.registerInterceptors();
-
DaoRegistry daoRegistry = myAppCtx.getBean(DaoRegistry.class);
IInterceptorBroadcaster interceptorBroadcaster = myAppCtx.getBean(IInterceptorBroadcaster.class);
CascadingDeleteInterceptor cascadingDeleteInterceptor = new CascadingDeleteInterceptor(daoRegistry, interceptorBroadcaster);
diff --git a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/config/DaoConfig.java b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/config/DaoConfig.java
index ae9f47c6c3e..d5c58153126 100644
--- a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/config/DaoConfig.java
+++ b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/config/DaoConfig.java
@@ -1559,28 +1559,6 @@ public class DaoConfig {
myEnableInMemorySubscriptionMatching = theEnableInMemorySubscriptionMatching;
}
- /**
- * If set to true (default is true) the server will match incoming resources against active subscriptions
- * and send them to the subscription channel. If set to false no matching or sending occurs.
- *
- * @since 3.7.0
- */
-
- public boolean isSubscriptionMatchingEnabled() {
- return myModelConfig.isSubscriptionMatchingEnabled();
- }
-
- /**
- * If set to true (default is true) the server will match incoming resources against active subscriptions
- * and send them to the subscription channel. If set to false no matching or sending occurs.
- *
- * @since 3.7.0
- */
-
- public void setSubscriptionMatchingEnabled(boolean theSubscriptionMatchingEnabled) {
- myModelConfig.setSubscriptionMatchingEnabled(theSubscriptionMatchingEnabled);
- }
-
public ModelConfig getModelConfig() {
return myModelConfig;
}
@@ -1703,6 +1681,8 @@ public class DaoConfig {
/**
* This setting indicates which subscription channel types are supported by the server. Any subscriptions submitted
* to the server matching these types will be activated.
+ *
+ * @see #addSupportedSubscriptionType(Subscription.SubscriptionChannelType)
*/
public Set getSupportedSubscriptionTypes() {
return myModelConfig.getSupportedSubscriptionTypes();
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/SubscriptionTestUtil.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/SubscriptionTestUtil.java
index 21deca15563..9dbf6fa3492 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/SubscriptionTestUtil.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/SubscriptionTestUtil.java
@@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.subscription;
import ca.uhn.fhir.jpa.api.config.DaoConfig;
import ca.uhn.fhir.jpa.subscription.channel.queue.LinkedBlockingQueueChannel;
-import ca.uhn.fhir.jpa.subscription.submit.interceptor.SubmitInterceptorLoader;
+import ca.uhn.fhir.jpa.subscription.submit.interceptor.SubscriptionSubmitInterceptorLoader;
import ca.uhn.fhir.jpa.subscription.process.registry.ActiveSubscription;
import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionRegistry;
import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionChannelRegistry;
@@ -22,7 +22,7 @@ public class SubscriptionTestUtil {
@Autowired
private DaoConfig myDaoConfig;
@Autowired
- private SubmitInterceptorLoader mySubmitInterceptorLoader;
+ private SubscriptionSubmitInterceptorLoader mySubscriptionSubmitInterceptorLoader;
@Autowired
private SubscriptionMatcherInterceptor mySubscriptionMatcherInterceptor;
@Autowired
@@ -50,22 +50,22 @@ public class SubscriptionTestUtil {
public void registerEmailInterceptor() {
myDaoConfig.addSupportedSubscriptionType(Subscription.SubscriptionChannelType.EMAIL);
- mySubmitInterceptorLoader.registerInterceptors();
+ mySubscriptionSubmitInterceptorLoader.start();
}
public void registerRestHookInterceptor() {
myDaoConfig.addSupportedSubscriptionType(Subscription.SubscriptionChannelType.RESTHOOK);
- mySubmitInterceptorLoader.registerInterceptors();
+ mySubscriptionSubmitInterceptorLoader.start();
}
public void registerWebSocketInterceptor() {
myDaoConfig.addSupportedSubscriptionType(Subscription.SubscriptionChannelType.WEBSOCKET);
- mySubmitInterceptorLoader.registerInterceptors();
+ mySubscriptionSubmitInterceptorLoader.start();
}
public void unregisterSubscriptionInterceptor() {
myDaoConfig.clearSupportedSubscriptionTypesForUnitTest();
- mySubmitInterceptorLoader.unregisterInterceptorsForUnitTest();
+ mySubscriptionSubmitInterceptorLoader.unregisterInterceptorsForUnitTest();
}
public int getExecutorQueueSizeForUnitTests() {
diff --git a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ModelConfig.java b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ModelConfig.java
index 171c6d31866..4448fc36955 100644
--- a/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ModelConfig.java
+++ b/hapi-fhir-jpaserver-model/src/main/java/ca/uhn/fhir/jpa/model/entity/ModelConfig.java
@@ -58,7 +58,6 @@ public class ModelConfig {
private boolean myDefaultSearchParamsCanBeOverridden = false;
private Set mySupportedSubscriptionTypes = new HashSet<>();
private String myEmailFromAddress = "noreply@unknown.com";
- private boolean mySubscriptionMatchingEnabled = true;
private String myWebsocketContextPath = DEFAULT_WEBSOCKET_CONTEXT_PATH;
/**
@@ -330,27 +329,6 @@ public class ModelConfig {
return Collections.unmodifiableSet(mySupportedSubscriptionTypes);
}
- /**
- * If set to true (default is true) the server will match incoming resources against active subscriptions
- * and send them to the subscription channel. If set to false no matching or sending occurs.
- * @since 3.7.0
- */
-
- public boolean isSubscriptionMatchingEnabled() {
- return mySubscriptionMatchingEnabled;
- }
-
- /**
- * If set to true (default is true) the server will match incoming resources against active subscriptions
- * and send them to the subscription channel. If set to false no matching or sending occurs.
- * @since 3.7.0
- */
-
-
- public void setSubscriptionMatchingEnabled(boolean theSubscriptionMatchingEnabled) {
- mySubscriptionMatchingEnabled = theSubscriptionMatchingEnabled;
- }
-
@VisibleForTesting
public void clearSupportedSubscriptionTypesForUnitTest() {
mySupportedSubscriptionTypes.clear();
diff --git a/hapi-fhir-jpaserver-subscription/pom.xml b/hapi-fhir-jpaserver-subscription/pom.xml
index 43cd8b96d32..d99b38a38c4 100644
--- a/hapi-fhir-jpaserver-subscription/pom.xml
+++ b/hapi-fhir-jpaserver-subscription/pom.xml
@@ -78,6 +78,11 @@
+
+ ca.uhn.hapi.fhir
+ hapi-fhir-test-utilities
+ ${project.version}
+ org.springframeworkspring-test
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/IQueueChannelFactory.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/IQueueChannelFactory.java
index e764be57fe4..92321b7f44b 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/IQueueChannelFactory.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/IQueueChannelFactory.java
@@ -50,9 +50,4 @@ public interface IQueueChannelFactory {
*/
MessageChannel getOrCreateSender(String theChannelName, Class> theMessageType, int theConcurrentConsumers);
- // FIXME: can these be removed?
- int getDeliveryChannelConcurrentConsumers();
-
- // FIXME: can these be removed?
- int getMatchingChannelConcurrentConsumers();
}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/LinkedBlockingQueueChannelFactory.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/LinkedBlockingQueueChannelFactory.java
index d75809d765a..07c2f0f710a 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/LinkedBlockingQueueChannelFactory.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/LinkedBlockingQueueChannelFactory.java
@@ -33,6 +33,13 @@ public class LinkedBlockingQueueChannelFactory implements IQueueChannelFactory {
private Map myChannels = Collections.synchronizedMap(new HashMap<>());
+ /**
+ * Constructor
+ */
+ public LinkedBlockingQueueChannelFactory() {
+ super();
+ }
+
@Override
public SubscribableChannel getOrCreateReceiver(String theChannelName, Class> theMessageType, int theConcurrentConsumers) {
return getOrCreateChannel(theChannelName, theConcurrentConsumers);
@@ -44,17 +51,11 @@ public class LinkedBlockingQueueChannelFactory implements IQueueChannelFactory {
}
private SubscribableChannel getOrCreateChannel(String theChannelName, int theConcurrentConsumers) {
- return myChannels.computeIfAbsent(theChannelName, t ->
- new LinkedBlockingQueueChannel(new LinkedBlockingQueue<>(SubscriptionConstants.DELIVERY_EXECUTOR_QUEUE_SIZE), theChannelName + "-%d", theConcurrentConsumers));
+ return myChannels.computeIfAbsent(theChannelName, t -> {
+ LinkedBlockingQueue queue = new LinkedBlockingQueue<>(SubscriptionConstants.DELIVERY_EXECUTOR_QUEUE_SIZE);
+ String threadNamingPattern = theChannelName + "-%d";
+ return new LinkedBlockingQueueChannel(queue, threadNamingPattern, theConcurrentConsumers);
+ });
}
- @Override
- public int getDeliveryChannelConcurrentConsumers() {
- return SubscriptionConstants.DELIVERY_CHANNEL_CONCURRENT_CONSUMERS;
- }
-
- @Override
- public int getMatchingChannelConcurrentConsumers() {
- return SubscriptionConstants.MATCHING_CHANNEL_CONCURRENT_CONSUMERS;
- }
}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelFactory.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelFactory.java
index 03b5704d650..70da786f8a4 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelFactory.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelFactory.java
@@ -20,12 +20,17 @@ package ca.uhn.fhir.jpa.subscription.channel.subscription;
* #L%
*/
-import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage;
import ca.uhn.fhir.jpa.subscription.channel.queue.IQueueChannelFactory;
import ca.uhn.fhir.jpa.subscription.model.ResourceDeliveryMessage;
+import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage;
+import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionConstants;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
+import org.springframework.messaging.MessageHandler;
+import org.springframework.messaging.MessagingException;
import org.springframework.messaging.SubscribableChannel;
+import org.springframework.messaging.support.AbstractSubscribableChannel;
public class SubscriptionChannelFactory {
@@ -33,15 +38,48 @@ public class SubscriptionChannelFactory {
private IQueueChannelFactory mySubscribableChannelFactory;
public SubscribableChannel newDeliveryChannel(String theChannelName) {
- return mySubscribableChannelFactory.getOrCreateReceiver(theChannelName, ResourceDeliveryMessage.class, mySubscribableChannelFactory.getDeliveryChannelConcurrentConsumers());
+ SubscribableChannel channel = mySubscribableChannelFactory.getOrCreateReceiver(theChannelName, ResourceDeliveryMessage.class, getDeliveryChannelConcurrentConsumers());
+ return new BroadcastingSubscribableChannelWrapper(channel);
}
public MessageChannel newMatchingSendingChannel(String theChannelName) {
- return mySubscribableChannelFactory.getOrCreateSender(theChannelName, ResourceModifiedMessage.class, mySubscribableChannelFactory.getMatchingChannelConcurrentConsumers());
+ return mySubscribableChannelFactory.getOrCreateSender(theChannelName, ResourceModifiedMessage.class, getMatchingChannelConcurrentConsumers());
}
public SubscribableChannel newMatchingReceivingChannel(String theChannelName) {
- return mySubscribableChannelFactory.getOrCreateReceiver(theChannelName, ResourceModifiedMessage.class, mySubscribableChannelFactory.getMatchingChannelConcurrentConsumers());
+ SubscribableChannel channel = mySubscribableChannelFactory.getOrCreateReceiver(theChannelName, ResourceModifiedMessage.class, getMatchingChannelConcurrentConsumers());
+ return new BroadcastingSubscribableChannelWrapper(channel);
}
+ public int getDeliveryChannelConcurrentConsumers() {
+ return SubscriptionConstants.DELIVERY_CHANNEL_CONCURRENT_CONSUMERS;
+ }
+
+ public int getMatchingChannelConcurrentConsumers() {
+ return SubscriptionConstants.MATCHING_CHANNEL_CONCURRENT_CONSUMERS;
+ }
+
+
+ private static class BroadcastingSubscribableChannelWrapper extends AbstractSubscribableChannel implements MessageHandler {
+
+ public BroadcastingSubscribableChannelWrapper(SubscribableChannel theChannel) {
+ theChannel.subscribe(this);
+ }
+
+
+ @Override
+ protected boolean sendInternal(Message> theMessage, long timeout) {
+ for (MessageHandler next : getSubscribers()) {
+ next.handleMessage(theMessage);
+ }
+ return true;
+ }
+
+ @Override
+ public void handleMessage(Message> message) throws MessagingException {
+ send(message);
+ }
+ }
+
+
}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelRegistry.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelRegistry.java
index 4a1e782cdee..1661d132573 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelRegistry.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelRegistry.java
@@ -51,9 +51,6 @@ public class SubscriptionChannelRegistry {
private ModelConfig myModelConfig;
public synchronized void add(ActiveSubscription theActiveSubscription) {
- if (!myModelConfig.isSubscriptionMatchingEnabled()) {
- return;
- }
String channelName = theActiveSubscription.getChannelName();
ourLog.info("Adding subscription {} to channel {}", theActiveSubscription.getId(), channelName);
myActiveSubscriptionByChannelName.put(channelName, theActiveSubscription.getId());
@@ -75,9 +72,6 @@ public class SubscriptionChannelRegistry {
}
public synchronized void remove(ActiveSubscription theActiveSubscription) {
- if (!myModelConfig.isSubscriptionMatchingEnabled()) {
- return;
- }
String channelName = theActiveSubscription.getChannelName();
ourLog.info("Removing subscription {} from channel {}", theActiveSubscription.getId() ,channelName);
boolean removed = myActiveSubscriptionByChannelName.remove(channelName, theActiveSubscription.getId());
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/model/config/SubscriptionModelConfig.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/model/config/SubscriptionModelConfig.java
new file mode 100644
index 00000000000..2812747cf41
--- /dev/null
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/model/config/SubscriptionModelConfig.java
@@ -0,0 +1,44 @@
+package ca.uhn.fhir.jpa.subscription.model.config;
+
+/*-
+ * #%L
+ * HAPI FHIR Subscription Server
+ * %%
+ * Copyright (C) 2014 - 2020 University Health Network
+ * %%
+ * 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%
+ */
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.jpa.subscription.process.matcher.matching.SubscriptionStrategyEvaluator;
+import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionCanonicalizer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class SubscriptionModelConfig {
+
+ @Bean
+ public SubscriptionCanonicalizer subscriptionCanonicalizer(FhirContext theFhirContext) {
+ return new SubscriptionCanonicalizer(theFhirContext);
+ }
+
+
+ @Bean
+ public SubscriptionStrategyEvaluator subscriptionStrategyEvaluator() {
+ return new SubscriptionStrategyEvaluator();
+ }
+
+
+}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/config/SubscriptionProcessorConfig.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/config/SubscriptionProcessorConfig.java
index 88151a43de1..1f7eed79122 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/config/SubscriptionProcessorConfig.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/config/SubscriptionProcessorConfig.java
@@ -20,10 +20,10 @@ package ca.uhn.fhir.jpa.subscription.process.config;
* #L%
*/
-import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionChannelRegistry;
import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionDeliveryChannelNamer;
import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionDeliveryHandlerFactory;
+import ca.uhn.fhir.jpa.subscription.model.config.SubscriptionModelConfig;
import ca.uhn.fhir.jpa.subscription.process.deliver.DaoResourceRetriever;
import ca.uhn.fhir.jpa.subscription.process.deliver.IResourceRetriever;
import ca.uhn.fhir.jpa.subscription.process.deliver.email.IEmailSender;
@@ -34,19 +34,18 @@ import ca.uhn.fhir.jpa.subscription.process.matcher.matching.CompositeInMemoryDa
import ca.uhn.fhir.jpa.subscription.process.matcher.matching.DaoSubscriptionMatcher;
import ca.uhn.fhir.jpa.subscription.process.matcher.matching.ISubscriptionMatcher;
import ca.uhn.fhir.jpa.subscription.process.matcher.matching.InMemorySubscriptionMatcher;
-import ca.uhn.fhir.jpa.subscription.process.matcher.matching.SubscriptionStrategyEvaluator;
import ca.uhn.fhir.jpa.subscription.process.matcher.subscriber.MatchingQueueSubscriberLoader;
import ca.uhn.fhir.jpa.subscription.process.matcher.subscriber.SubscriptionActivatingSubscriber;
import ca.uhn.fhir.jpa.subscription.process.matcher.subscriber.SubscriptionMatchingSubscriber;
import ca.uhn.fhir.jpa.subscription.process.matcher.subscriber.SubscriptionRegisteringSubscriber;
import ca.uhn.fhir.jpa.subscription.process.registry.DaoSubscriptionProvider;
import ca.uhn.fhir.jpa.subscription.process.registry.ISubscriptionProvider;
-import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionCanonicalizer;
import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionLoader;
import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionRegistry;
import ca.uhn.fhir.jpa.subscription.triggering.ISubscriptionTriggeringSvc;
import ca.uhn.fhir.jpa.subscription.triggering.SubscriptionTriggeringSvcImpl;
import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Scope;
@@ -55,6 +54,7 @@ import org.springframework.context.annotation.Scope;
* This Spring config should be imported by a system that pulls messages off of the
* matching queue for processing, and handles delivery
*/
+@Import(SubscriptionModelConfig.class)
public class SubscriptionProcessorConfig {
@Bean
@@ -102,16 +102,6 @@ public class SubscriptionProcessorConfig {
return new WebsocketConnectionValidator();
}
- @Bean
- public SubscriptionStrategyEvaluator subscriptionStrategyEvaluator() {
- return new SubscriptionStrategyEvaluator();
- }
-
- @Bean
- public SubscriptionCanonicalizer subscriptionCanonicalizer(FhirContext theFhirContext) {
- return new SubscriptionCanonicalizer(theFhirContext);
- }
-
@Bean
public SubscriptionLoader subscriptionLoader() {
return new SubscriptionLoader();
@@ -127,12 +117,6 @@ public class SubscriptionProcessorConfig {
return new SubscriptionDeliveryHandlerFactory();
}
- @Bean
- @Lazy
- public ISubscriptionTriggeringSvc subscriptionTriggeringSvc() {
- return new SubscriptionTriggeringSvcImpl();
- }
-
@Bean
@Scope("prototype")
public SubscriptionDeliveringRestHookSubscriber subscriptionDeliveringRestHookSubscriber() {
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/IResourceModifiedConsumer.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/IResourceModifiedConsumer.java
index 577dbc4e2fc..d03b0054ad7 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/IResourceModifiedConsumer.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/IResourceModifiedConsumer.java
@@ -21,7 +21,19 @@ package ca.uhn.fhir.jpa.subscription.process.matcher.matching;
*/
import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage;
+import ca.uhn.fhir.rest.api.server.RequestDetails;
+import org.hl7.fhir.instance.model.api.IBaseResource;
public interface IResourceModifiedConsumer {
+
+ /**
+ * This is an internal API - Use with caution!
+ */
+ void submitResourceModified(IBaseResource theNewResource, ResourceModifiedMessage.OperationTypeEnum theOperationType, RequestDetails theRequest);
+
+ /**
+ * This is an internal API - Use with caution!
+ */
void submitResourceModified(ResourceModifiedMessage theMsg);
+
}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/SubscriptionStrategyEvaluator.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/SubscriptionStrategyEvaluator.java
index 04239f38839..e0ac8dbcdbc 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/SubscriptionStrategyEvaluator.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/SubscriptionStrategyEvaluator.java
@@ -29,6 +29,13 @@ public class SubscriptionStrategyEvaluator {
@Autowired
private InMemoryResourceMatcher myInMemoryResourceMatcher;
+ /**
+ * Constructor
+ */
+ public SubscriptionStrategyEvaluator() {
+ super();
+ }
+
public SubscriptionMatchingStrategy determineStrategy(String theCriteria) {
InMemoryMatchResult result = myInMemoryResourceMatcher.match(theCriteria, null, null);
if (result.supported()) {
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionActivatingSubscriber.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionActivatingSubscriber.java
index ddc167ee6cd..8f35ce3b196 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionActivatingSubscriber.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionActivatingSubscriber.java
@@ -24,43 +24,29 @@ import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.jpa.api.config.DaoConfig;
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
-import ca.uhn.fhir.jpa.subscription.model.CanonicalSubscription;
import ca.uhn.fhir.jpa.subscription.model.CanonicalSubscriptionChannelType;
+import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedJsonMessage;
import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage;
+import ca.uhn.fhir.jpa.subscription.process.matcher.matching.SubscriptionStrategyEvaluator;
import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionCanonicalizer;
import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionConstants;
import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionRegistry;
-import ca.uhn.fhir.jpa.subscription.process.matcher.matching.SubscriptionMatchingStrategy;
-import ca.uhn.fhir.jpa.subscription.process.matcher.matching.SubscriptionStrategyEvaluator;
-import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedJsonMessage;
import ca.uhn.fhir.model.dstu2.valueset.ResourceTypeEnum;
-import ca.uhn.fhir.parser.DataFormatException;
-import ca.uhn.fhir.rest.api.EncodingEnum;
-import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.util.SubscriptionUtil;
-import com.google.common.annotations.VisibleForTesting;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.MessagingException;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
-import org.springframework.transaction.support.TransactionSynchronizationAdapter;
-import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.transaction.support.TransactionTemplate;
import javax.annotation.Nonnull;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-
-import static org.apache.commons.lang3.StringUtils.isBlank;
/**
* Responsible for transitioning subscription resources from REQUESTED to ACTIVE
@@ -69,14 +55,9 @@ import static org.apache.commons.lang3.StringUtils.isBlank;
* Also validates criteria. If invalid, rejects the subscription without persisting the subscription.
*/
public class SubscriptionActivatingSubscriber extends BaseSubscriberForSubscriptionResources implements MessageHandler {
- private static boolean ourWaitForSubscriptionActivationSynchronouslyForUnitTest;
private Logger ourLog = LoggerFactory.getLogger(SubscriptionActivatingSubscriber.class);
@Autowired
private PlatformTransactionManager myTransactionManager;
- // FIXME: use constant if this is still needed
- @Autowired
- @Qualifier("hapiJpaTaskExecutor")
- private AsyncTaskExecutor myTaskExecutor;
@Autowired
private SubscriptionRegistry mySubscriptionRegistry;
@Autowired
@@ -133,43 +114,7 @@ public class SubscriptionActivatingSubscriber extends BaseSubscriberForSubscript
String statusString = mySubscriptionCanonicalizer.getSubscriptionStatus(theSubscription);
if (SubscriptionConstants.REQUESTED_STATUS.equals(statusString)) {
- if (TransactionSynchronizationManager.isSynchronizationActive()) {
- /*
- * If we're in a transaction, we don't want to try and change the status from
- * requested to active within the same transaction because it's too late by
- * the time we get here to make modifications to the payload.
- *
- * So, we register a synchronization, meaning that when the transaction is
- * finished, we'll schedule a task to do this in a separate worker thread
- * to avoid any possibility of conflict.
- */
- TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
- @Override
- public void afterCommit() {
- Future> activationFuture = myTaskExecutor.submit(new Runnable() {
- @Override
- public void run() {
- activateSubscription(SubscriptionConstants.ACTIVE_STATUS, theSubscription, SubscriptionConstants.REQUESTED_STATUS);
- }
- });
-
- /*
- * If we're running in a unit test, it's nice to be predictable in
- * terms of order... In the real world it's a recipe for deadlocks
- */
- if (ourWaitForSubscriptionActivationSynchronouslyForUnitTest) {
- try {
- activationFuture.get(5, TimeUnit.SECONDS);
- } catch (Exception e) {
- ourLog.error("Failed to activate subscription", e);
- }
- }
- }
- });
- return true;
- } else {
- return activateSubscription(SubscriptionConstants.ACTIVE_STATUS, theSubscription, SubscriptionConstants.REQUESTED_STATUS);
- }
+ return activateSubscription(theSubscription);
} else if (SubscriptionConstants.ACTIVE_STATUS.equals(statusString)) {
return mySubscriptionRegistry.registerSubscriptionUnlessAlreadyRegistered(theSubscription);
} else {
@@ -179,14 +124,14 @@ public class SubscriptionActivatingSubscriber extends BaseSubscriberForSubscript
}
@SuppressWarnings("unchecked")
- private boolean activateSubscription(String theActiveStatus, final IBaseResource theSubscription, String theRequestedStatus) {
+ private boolean activateSubscription(final IBaseResource theSubscription) {
IFhirResourceDao subscriptionDao = myDaoRegistry.getSubscriptionDao();
IBaseResource subscription = subscriptionDao.read(theSubscription.getIdElement());
subscription.setId(subscription.getIdElement().toVersionless());
- ourLog.info("Activating subscription {} from status {} to {}", subscription.getIdElement().toUnqualified().getValue(), theRequestedStatus, theActiveStatus);
+ ourLog.info("Activating subscription {} from status {} to {}", subscription.getIdElement().toUnqualified().getValue(), SubscriptionConstants.REQUESTED_STATUS, SubscriptionConstants.ACTIVE_STATUS);
try {
- SubscriptionUtil.setStatus(myFhirContext, subscription, theActiveStatus);
+ SubscriptionUtil.setStatus(myFhirContext, subscription, SubscriptionConstants.ACTIVE_STATUS);
subscriptionDao.update(subscription);
return true;
} catch (final UnprocessableEntityException e) {
@@ -214,9 +159,4 @@ public class SubscriptionActivatingSubscriber extends BaseSubscriberForSubscript
});
}
- @VisibleForTesting
- public static void setWaitForSubscriptionActivationSynchronouslyForUnitTest(boolean theWaitForSubscriptionActivationSynchronouslyForUnitTest) {
- ourWaitForSubscriptionActivationSynchronouslyForUnitTest = theWaitForSubscriptionActivationSynchronouslyForUnitTest;
- }
-
}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionMatchingSubscriber.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionMatchingSubscriber.java
index 2f8ff1632a8..441ff31b8d2 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionMatchingSubscriber.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionMatchingSubscriber.java
@@ -67,6 +67,13 @@ public class SubscriptionMatchingSubscriber implements MessageHandler {
@Autowired
private SubscriptionChannelRegistry mySubscriptionChannelRegistry;
+ /**
+ * Constructor
+ */
+ public SubscriptionMatchingSubscriber() {
+ super();
+ }
+
@Override
public void handleMessage(@Nonnull Message> theMessage) throws MessagingException {
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/SubscriptionLoader.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/SubscriptionLoader.java
index 59e66b77696..90757e100f0 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/SubscriptionLoader.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/SubscriptionLoader.java
@@ -59,6 +59,13 @@ public class SubscriptionLoader {
@Autowired
private ISchedulerService mySchedulerService;
+ /**
+ * Constructor
+ */
+ public SubscriptionLoader() {
+ super();
+ }
+
/**
* Read the existing subscriptions from the database
*/
@@ -76,18 +83,14 @@ public class SubscriptionLoader {
}
}
- @VisibleForTesting
- void acquireSemaphoreForUnitTest() throws InterruptedException {
- mySyncSubscriptionsSemaphore.acquire();
- }
-
-
@PostConstruct
public void scheduleJob() {
ScheduledJobDefinition jobDetail = new ScheduledJobDefinition();
jobDetail.setId(getClass().getName());
jobDetail.setJobClass(Job.class);
mySchedulerService.scheduleLocalJob(DateUtils.MILLIS_PER_MINUTE, jobDetail);
+
+ syncSubscriptions();
}
public static class Job implements HapiJob {
@@ -158,9 +161,5 @@ public class SubscriptionLoader {
}
}
- @VisibleForTesting
- public void setSubscriptionProviderForUnitTest(ISubscriptionProvider theSubscriptionProvider) {
- mySubscriptionProvider = theSubscriptionProvider;
- }
}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/config/SubscriptionSubmitterConfig.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/config/SubscriptionSubmitterConfig.java
index edbb96c5296..b0eb39b0213 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/config/SubscriptionSubmitterConfig.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/config/SubscriptionSubmitterConfig.java
@@ -20,17 +20,23 @@ package ca.uhn.fhir.jpa.subscription.submit.config;
* #L%
*/
+import ca.uhn.fhir.jpa.subscription.model.config.SubscriptionModelConfig;
import ca.uhn.fhir.jpa.subscription.submit.interceptor.SubscriptionMatcherInterceptor;
-import ca.uhn.fhir.jpa.subscription.submit.interceptor.SubmitInterceptorLoader;
+import ca.uhn.fhir.jpa.subscription.submit.interceptor.SubscriptionSubmitInterceptorLoader;
import ca.uhn.fhir.jpa.subscription.submit.interceptor.SubscriptionValidatingInterceptor;
+import ca.uhn.fhir.jpa.subscription.triggering.ISubscriptionTriggeringSvc;
+import ca.uhn.fhir.jpa.subscription.triggering.SubscriptionTriggeringSvcImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import org.springframework.context.annotation.Lazy;
/**
* This Spring config should be imported by a system that submits resources to the
* matching queue for processing
*/
@Configuration
+@Import(SubscriptionModelConfig.class)
public class SubscriptionSubmitterConfig {
@Bean
@@ -44,8 +50,15 @@ public class SubscriptionSubmitterConfig {
}
@Bean
- public SubmitInterceptorLoader subscriptionMatcherInterceptorLoader() {
- return new SubmitInterceptorLoader();
+ public SubscriptionSubmitInterceptorLoader subscriptionMatcherInterceptorLoader() {
+ return new SubscriptionSubmitInterceptorLoader();
}
+ @Bean
+ @Lazy
+ public ISubscriptionTriggeringSvc subscriptionTriggeringSvc() {
+ return new SubscriptionTriggeringSvcImpl();
+ }
+
+
}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionMatcherInterceptor.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionMatcherInterceptor.java
index d5c2371063b..0877bc1f4c5 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionMatcherInterceptor.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionMatcherInterceptor.java
@@ -52,8 +52,6 @@ public class SubscriptionMatcherInterceptor implements IResourceModifiedConsumer
@Autowired
private FhirContext myFhirContext;
@Autowired
- private SubscriptionMatchingSubscriber mySubscriptionMatchingSubscriber;
- @Autowired
private IInterceptorBroadcaster myInterceptorBroadcaster;
@Autowired
private SubscriptionChannelFactory mySubscriptionChannelFactory;
@@ -87,7 +85,11 @@ public class SubscriptionMatcherInterceptor implements IResourceModifiedConsumer
submitResourceModified(theNewResource, ResourceModifiedMessage.OperationTypeEnum.UPDATE, theRequest);
}
- private void submitResourceModified(IBaseResource theNewResource, ResourceModifiedMessage.OperationTypeEnum theOperationType, RequestDetails theRequest) {
+ /**
+ * This is an internal API - Use with caution!
+ */
+ @Override
+ public void submitResourceModified(IBaseResource theNewResource, ResourceModifiedMessage.OperationTypeEnum theOperationType, RequestDetails theRequest) {
ResourceModifiedMessage msg = new ResourceModifiedMessage(myFhirContext, theNewResource, theOperationType);
// Interceptor call: SUBSCRIPTION_RESOURCE_MODIFIED
@@ -101,16 +103,6 @@ public class SubscriptionMatcherInterceptor implements IResourceModifiedConsumer
submitResourceModified(msg);
}
- protected void sendToProcessingChannel(final ResourceModifiedMessage theMessage) {
- ourLog.trace("Sending resource modified message to processing channel");
- Validate.notNull(myMatchingChannel, "A SubscriptionMatcherInterceptor has been registered without calling start() on it.");
- myMatchingChannel.send(new ResourceModifiedJsonMessage(theMessage));
- }
-
- public void setFhirContext(FhirContext theCtx) {
- myFhirContext = theCtx;
- }
-
/**
* This is an internal API - Use with caution!
*/
@@ -138,6 +130,16 @@ public class SubscriptionMatcherInterceptor implements IResourceModifiedConsumer
}
}
+ protected void sendToProcessingChannel(final ResourceModifiedMessage theMessage) {
+ ourLog.trace("Sending resource modified message to processing channel");
+ Validate.notNull(myMatchingChannel, "A SubscriptionMatcherInterceptor has been registered without calling start() on it.");
+ myMatchingChannel.send(new ResourceModifiedJsonMessage(theMessage));
+ }
+
+ public void setFhirContext(FhirContext theCtx) {
+ myFhirContext = theCtx;
+ }
+
@VisibleForTesting
public LinkedBlockingQueueChannel getProcessingChannelForUnitTest() {
return (LinkedBlockingQueueChannel) myMatchingChannel;
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubmitInterceptorLoader.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionSubmitInterceptorLoader.java
similarity index 61%
rename from hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubmitInterceptorLoader.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionSubmitInterceptorLoader.java
index c6715a95232..a827abc7462 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubmitInterceptorLoader.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionSubmitInterceptorLoader.java
@@ -22,10 +22,6 @@ package ca.uhn.fhir.jpa.subscription.submit.interceptor;
import ca.uhn.fhir.interceptor.api.IInterceptorService;
import ca.uhn.fhir.jpa.api.config.DaoConfig;
-import ca.uhn.fhir.jpa.subscription.process.matcher.subscriber.SubscriptionActivatingSubscriber;
-import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionLoader;
-import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionRegistry;
-import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionChannelRegistry;
import com.google.common.annotations.VisibleForTesting;
import org.hl7.fhir.dstu2.model.Subscription;
import org.slf4j.Logger;
@@ -33,52 +29,38 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
+import javax.annotation.PostConstruct;
import java.util.Set;
-public class SubmitInterceptorLoader {
- private static final Logger ourLog = LoggerFactory.getLogger(SubmitInterceptorLoader.class);
+public class SubscriptionSubmitInterceptorLoader {
+ private static final Logger ourLog = LoggerFactory.getLogger(SubscriptionSubmitInterceptorLoader.class);
@Autowired
private SubscriptionMatcherInterceptor mySubscriptionMatcherInterceptor;
@Autowired
private SubscriptionValidatingInterceptor mySubscriptionValidatingInterceptor;
@Autowired
- DaoConfig myDaoConfig;
- @Autowired
- private SubscriptionRegistry mySubscriptionRegistry;
- @Autowired
- private SubscriptionChannelRegistry mySubscriptionChannelRegistry;
+ private DaoConfig myDaoConfig;
@Autowired
private ApplicationContext myApplicationContext;
@Autowired
private IInterceptorService myInterceptorRegistry;
- public void registerInterceptors() {
+ @PostConstruct
+ public void start() {
Set supportedSubscriptionTypes = myDaoConfig.getSupportedSubscriptionTypes();
if (supportedSubscriptionTypes.isEmpty()) {
ourLog.info("Subscriptions are disabled on this server. Subscriptions will not be activated and incoming resources will not be matched against subscriptions.");
} else {
- loadSubscriptions();
- if (myDaoConfig.isSubscriptionMatchingEnabled()) {
- mySubscriptionMatcherInterceptor.start();
- ourLog.info("Registering subscription matcher interceptor");
- myInterceptorRegistry.registerInterceptor(mySubscriptionMatcherInterceptor);
- }
+ mySubscriptionMatcherInterceptor.start();
+ ourLog.info("Registering subscription matcher interceptor");
+ myInterceptorRegistry.registerInterceptor(mySubscriptionMatcherInterceptor);
}
myInterceptorRegistry.registerInterceptor(mySubscriptionValidatingInterceptor);
}
- private void loadSubscriptions() {
- ourLog.info("Loading subscriptions into the SubscriptionRegistry...");
- // Load active subscriptions into the SubscriptionRegistry and activate their channels
- SubscriptionLoader loader = myApplicationContext.getBean(SubscriptionLoader.class);
- loader.syncSubscriptions();
- ourLog.info("...{} subscriptions loaded", mySubscriptionRegistry.size());
- ourLog.info("...{} subscription channels started", mySubscriptionChannelRegistry.size());
- }
-
@VisibleForTesting
public void unregisterInterceptorsForUnitTest() {
myInterceptorRegistry.unregisterInterceptor(mySubscriptionMatcherInterceptor);
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionValidatingInterceptor.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionValidatingInterceptor.java
index 237d22a38e6..4cf26006cbe 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionValidatingInterceptor.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionValidatingInterceptor.java
@@ -108,12 +108,7 @@ public class SubscriptionValidatingInterceptor {
throw new UnprocessableEntityException("Subscription.criteria must be in the form \"{Resource Type}?[params]\"");
}
- if (subscription.getChannelType() == null) {
- throw new UnprocessableEntityException("Subscription.channel.type must be populated");
- } else if (subscription.getChannelType() == CanonicalSubscriptionChannelType.RESTHOOK) {
- validateChannelPayload(subscription);
- validateChannelEndpoint(subscription);
- }
+ validateChannelType(subscription);
if (!myDaoRegistry.isResourceTypeSupported(resType)) {
throw new UnprocessableEntityException("Subscription.criteria contains invalid/unsupported resource type: " + resType);
@@ -133,6 +128,16 @@ public class SubscriptionValidatingInterceptor {
}
}
+ @SuppressWarnings("WeakerAccess")
+ protected void validateChannelType(CanonicalSubscription theSubscription) {
+ if (theSubscription.getChannelType() == null) {
+ throw new UnprocessableEntityException("Subscription.channel.type must be populated");
+ } else if (theSubscription.getChannelType() == CanonicalSubscriptionChannelType.RESTHOOK) {
+ validateChannelPayload(theSubscription);
+ validateChannelEndpoint(theSubscription);
+ }
+ }
+
@SuppressWarnings("WeakerAccess")
protected void validateChannelEndpoint(CanonicalSubscription theResource) {
if (isBlank(theResource.getEndpointUrl())) {
diff --git a/hapi-fhir-jpaserver-subscription/src/test/java/ca/uhn/fhir/jpa/subscription/module/channel/SubscriptionChannelRegistryTest.java b/hapi-fhir-jpaserver-subscription/src/test/java/ca/uhn/fhir/jpa/subscription/module/channel/SubscriptionChannelRegistryTest.java
index 0fb9edac08d..d16ad8f0a88 100644
--- a/hapi-fhir-jpaserver-subscription/src/test/java/ca/uhn/fhir/jpa/subscription/module/channel/SubscriptionChannelRegistryTest.java
+++ b/hapi-fhir-jpaserver-subscription/src/test/java/ca/uhn/fhir/jpa/subscription/module/channel/SubscriptionChannelRegistryTest.java
@@ -42,8 +42,6 @@ public class SubscriptionChannelRegistryTest {
@Test
public void testAddAddRemoveRemove() {
- when(myModelConfig.isSubscriptionMatchingEnabled()).thenReturn(true);
-
CanonicalSubscription cansubA = new CanonicalSubscription();
cansubA.setIdElement(new IdDt("A"));
ActiveSubscription activeSubscriptionA = new ActiveSubscription(cansubA, TEST_CHANNEL_NAME);
diff --git a/hapi-fhir-jpaserver-subscription/src/test/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionSubmitInterceptorLoaderTest.java b/hapi-fhir-jpaserver-subscription/src/test/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionSubmitInterceptorLoaderTest.java
new file mode 100644
index 00000000000..de8f1910397
--- /dev/null
+++ b/hapi-fhir-jpaserver-subscription/src/test/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionSubmitInterceptorLoaderTest.java
@@ -0,0 +1,85 @@
+package ca.uhn.fhir.jpa.subscription.submit.interceptor;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.context.support.IValidationSupport;
+import ca.uhn.fhir.interceptor.api.IInterceptorService;
+import ca.uhn.fhir.jpa.api.config.DaoConfig;
+import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
+import ca.uhn.fhir.jpa.model.entity.ModelConfig;
+import ca.uhn.fhir.jpa.model.sched.ISchedulerService;
+import ca.uhn.fhir.jpa.searchparam.config.SearchParamConfig;
+import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamProvider;
+import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionChannelFactory;
+import ca.uhn.fhir.jpa.subscription.submit.config.SubscriptionSubmitterConfig;
+import org.hl7.fhir.dstu2.model.Subscription;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+@RunWith(SpringRunner.class)
+@ContextConfiguration(classes = {
+ SubscriptionSubmitterConfig.class,
+ SearchParamConfig.class,
+ SubscriptionSubmitInterceptorLoaderTest.MyConfig.class
+})
+public class SubscriptionSubmitInterceptorLoaderTest {
+
+ @MockBean
+ private ISearchParamProvider mySearchParamProvider;
+ @MockBean
+ private ISchedulerService mySchedulerService;
+ @MockBean
+ private IInterceptorService myInterceptorService;
+ @MockBean
+ private IValidationSupport myValidationSupport;
+ @MockBean
+ private SubscriptionChannelFactory mySubscriptionChannelFactory;
+ @MockBean
+ private DaoRegistry myDaoRegistry;
+ @Autowired
+ private SubscriptionSubmitInterceptorLoader mySubscriptionSubmitInterceptorLoader;
+ @Autowired
+ private SubscriptionMatcherInterceptor mySubscriptionMatcherInterceptor;
+
+ /**
+ * It should be possible to run only the {@link SubscriptionSubmitterConfig} without the
+ * {@link ca.uhn.fhir.jpa.subscription.process.config.SubscriptionProcessorConfig}
+ */
+ @Test
+ public void testLoaderCanRunWithoutProcessorConfigLoaded() {
+ verify(myInterceptorService, times(1)).registerInterceptor(eq(mySubscriptionMatcherInterceptor));
+ }
+
+ @Configuration
+ public static class MyConfig {
+
+ @Bean
+ public FhirContext fhirContext() {
+ return FhirContext.forR4();
+ }
+
+ @Bean
+ public ModelConfig modelConfig() {
+ return new ModelConfig();
+ }
+
+ @Bean
+ public DaoConfig daoConfig() {
+ DaoConfig daoConfig = new DaoConfig();
+ daoConfig.addSupportedSubscriptionType(Subscription.SubscriptionChannelType.RESTHOOK);
+ return daoConfig;
+ }
+
+ }
+
+
+}
diff --git a/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/TestRestfulServer.java b/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/TestRestfulServer.java
index 68ae52c05cf..52d8ffaa687 100644
--- a/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/TestRestfulServer.java
+++ b/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/TestRestfulServer.java
@@ -20,7 +20,7 @@ import ca.uhn.fhir.jpa.provider.r5.JpaConformanceProviderR5;
import ca.uhn.fhir.jpa.provider.r5.JpaSystemProviderR5;
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
-import ca.uhn.fhir.jpa.subscription.submit.interceptor.SubmitInterceptorLoader;
+import ca.uhn.fhir.jpa.subscription.submit.interceptor.SubscriptionSubmitInterceptorLoader;
import ca.uhn.fhir.jpa.util.ResourceProviderFactory;
import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
import ca.uhn.fhir.rest.api.EncodingEnum;
@@ -252,12 +252,6 @@ public class TestRestfulServer extends RestfulServer {
*/
setPagingProvider(myAppCtx.getBean(DatabaseBackedPagingProvider.class));
- /*
- * Register subscription interceptors
- */
- SubmitInterceptorLoader submitInterceptorLoader = myAppCtx.getBean(SubmitInterceptorLoader.class);
- submitInterceptorLoader.registerInterceptors();
-
/*
* Cascading deletes
*/
From 79da1578cb45ac6213e15689a2188106421bab29 Mon Sep 17 00:00:00 2001
From: jamesagnew
Date: Sat, 4 Apr 2020 20:04:32 -0400
Subject: [PATCH 08/20] Subscription cleanup
---
.../fhir/jpa/dao/DaoSearchParamProvider.java | 9 +--
...rResourceDaoR4InvalidSubscriptionTest.java | 13 +---
...tivatesPreExistingSubscriptionsR4Test.java | 6 --
...rceptorRegisteredToDaoConfigDstu3Test.java | 16 ++--
.../SubscriptionChannelFactory.java | 13 +++-
.../matching/DaoSubscriptionMatcher.java | 7 +-
.../SubscriptionActivatingSubscriber.java | 10 +--
.../matching/DaoSubscriptionMatcherTest.java | 75 +++++++++++++++++++
8 files changed, 105 insertions(+), 44 deletions(-)
create mode 100644 hapi-fhir-jpaserver-subscription/src/test/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/DaoSubscriptionMatcherTest.java
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoSearchParamProvider.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoSearchParamProvider.java
index ddf4342c62e..07bb9b36c4c 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoSearchParamProvider.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoSearchParamProvider.java
@@ -22,22 +22,18 @@ package ca.uhn.fhir.jpa.dao;
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
-import ca.uhn.fhir.jpa.searchparam.registry.SearchParamRegistryImpl;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamProvider;
+import ca.uhn.fhir.jpa.searchparam.registry.SearchParamRegistryImpl;
import ca.uhn.fhir.model.dstu2.valueset.ResourceTypeEnum;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
-import org.springframework.transaction.PlatformTransactionManager;
-import org.springframework.transaction.support.TransactionTemplate;
@Service
@Primary
public class DaoSearchParamProvider implements ISearchParamProvider {
- @Autowired
- private PlatformTransactionManager myTxManager;
@Autowired
private DaoRegistry myDaoRegistry;
@@ -48,7 +44,6 @@ public class DaoSearchParamProvider implements ISearchParamProvider {
@Override
public int refreshCache(SearchParamRegistryImpl theSearchParamRegistry, long theRefreshInterval) {
- TransactionTemplate txTemplate = new TransactionTemplate(myTxManager);
- return txTemplate.execute(t-> theSearchParamRegistry.doRefresh(theRefreshInterval));
+ return theSearchParamRegistry.doRefresh(theRefreshInterval);
}
}
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4InvalidSubscriptionTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4InvalidSubscriptionTest.java
index d41d57f43aa..35c203ed6f4 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4InvalidSubscriptionTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4InvalidSubscriptionTest.java
@@ -1,8 +1,7 @@
package ca.uhn.fhir.jpa.dao.r4;
-import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
import ca.uhn.fhir.jpa.api.config.DaoConfig;
-import ca.uhn.fhir.jpa.subscription.process.matcher.subscriber.SubscriptionActivatingSubscriber;
+import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
import ca.uhn.fhir.jpa.subscription.SubscriptionTestUtil;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.util.TestUtil;
@@ -14,7 +13,8 @@ import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
public class FhirResourceDaoR4InvalidSubscriptionTest extends BaseJpaR4Test {
@@ -23,20 +23,13 @@ public class FhirResourceDaoR4InvalidSubscriptionTest extends BaseJpaR4Test {
@After
public void afterResetDao() {
- SubscriptionActivatingSubscriber.setWaitForSubscriptionActivationSynchronouslyForUnitTest(false);
myDaoConfig.setResourceServerIdStrategy(new DaoConfig().getResourceServerIdStrategy());
BaseHapiFhirDao.setValidationDisabledForUnitTest(false);
}
- @Before
- public void before() {
- SubscriptionActivatingSubscriber.setWaitForSubscriptionActivationSynchronouslyForUnitTest(true);
- }
-
@After
public void afterUnregisterRestHookListener() {
mySubscriptionTestUtil.unregisterSubscriptionInterceptor();
- SubscriptionActivatingSubscriber.setWaitForSubscriptionActivationSynchronouslyForUnitTest(false);
}
@Before
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/resthook/RestHookActivatesPreExistingSubscriptionsR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/resthook/RestHookActivatesPreExistingSubscriptionsR4Test.java
index e60b105c69d..4368f474659 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/resthook/RestHookActivatesPreExistingSubscriptionsR4Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/resthook/RestHookActivatesPreExistingSubscriptionsR4Test.java
@@ -45,11 +45,6 @@ public class RestHookActivatesPreExistingSubscriptionsR4Test extends BaseResourc
@Autowired
private SubscriptionTestUtil mySubscriptionTestUtil;
- @After
- public void afterResetSubscriptionActivatingInterceptor() {
- SubscriptionActivatingSubscriber.setWaitForSubscriptionActivationSynchronouslyForUnitTest(false);
- }
-
@After
public void afterUnregisterRestHookListener() {
mySubscriptionTestUtil.unregisterSubscriptionInterceptor();
@@ -57,7 +52,6 @@ public class RestHookActivatesPreExistingSubscriptionsR4Test extends BaseResourc
@Before
public void beforeSetSubscriptionActivatingInterceptor() {
- SubscriptionActivatingSubscriber.setWaitForSubscriptionActivationSynchronouslyForUnitTest(true);
mySubscriptionLoader.doSyncSubscriptionsForUnitTest();
}
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/resthook/RestHookTestWithInterceptorRegisteredToDaoConfigDstu3Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/resthook/RestHookTestWithInterceptorRegisteredToDaoConfigDstu3Test.java
index 552d851f3c1..04110bd6db6 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/resthook/RestHookTestWithInterceptorRegisteredToDaoConfigDstu3Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/resthook/RestHookTestWithInterceptorRegisteredToDaoConfigDstu3Test.java
@@ -4,7 +4,6 @@ package ca.uhn.fhir.jpa.subscription.resthook;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.api.config.DaoConfig;
import ca.uhn.fhir.jpa.provider.dstu3.BaseResourceProviderDstu3Test;
-import ca.uhn.fhir.jpa.subscription.process.matcher.subscriber.SubscriptionActivatingSubscriber;
import ca.uhn.fhir.jpa.subscription.SubscriptionTestUtil;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.annotation.Create;
@@ -18,9 +17,18 @@ import com.google.common.collect.Lists;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
-import org.hl7.fhir.dstu3.model.*;
+import org.hl7.fhir.dstu3.model.CodeableConcept;
+import org.hl7.fhir.dstu3.model.Coding;
+import org.hl7.fhir.dstu3.model.IdType;
+import org.hl7.fhir.dstu3.model.Observation;
+import org.hl7.fhir.dstu3.model.Subscription;
import org.hl7.fhir.instance.model.api.IBaseResource;
-import org.junit.*;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Collections;
@@ -56,7 +64,6 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigDstu3Test extends B
myDaoConfig.setAllowMultipleDelete(new DaoConfig().isAllowMultipleDelete());
mySubscriptionTestUtil.unregisterSubscriptionInterceptor();
- SubscriptionActivatingSubscriber.setWaitForSubscriptionActivationSynchronouslyForUnitTest(false);
}
@Before
@@ -68,7 +75,6 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigDstu3Test extends B
public void beforeReset() {
ourCreatedObservations.clear();
ourUpdatedObservations.clear();
- SubscriptionActivatingSubscriber.setWaitForSubscriptionActivationSynchronouslyForUnitTest(true);
}
private Subscription createSubscription(String criteria, String payload, String endpoint) throws InterruptedException {
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelFactory.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelFactory.java
index 70da786f8a4..30e207b952e 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelFactory.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelFactory.java
@@ -24,6 +24,7 @@ import ca.uhn.fhir.jpa.subscription.channel.queue.IQueueChannelFactory;
import ca.uhn.fhir.jpa.subscription.model.ResourceDeliveryMessage;
import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage;
import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionConstants;
+import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
@@ -60,10 +61,13 @@ public class SubscriptionChannelFactory {
}
- private static class BroadcastingSubscribableChannelWrapper extends AbstractSubscribableChannel implements MessageHandler {
+ private static class BroadcastingSubscribableChannelWrapper extends AbstractSubscribableChannel implements MessageHandler, DisposableBean {
+
+ private final SubscribableChannel myWrappedChannel;
public BroadcastingSubscribableChannelWrapper(SubscribableChannel theChannel) {
theChannel.subscribe(this);
+ myWrappedChannel = theChannel;
}
@@ -79,6 +83,13 @@ public class SubscriptionChannelFactory {
public void handleMessage(Message> message) throws MessagingException {
send(message);
}
+
+ @Override
+ public void destroy() throws Exception {
+ if (myWrappedChannel instanceof DisposableBean) {
+ ((DisposableBean) myWrappedChannel).destroy();
+ }
+ }
}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/DaoSubscriptionMatcher.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/DaoSubscriptionMatcher.java
index 3c9cb3437aa..d01676ad6f0 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/DaoSubscriptionMatcher.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/DaoSubscriptionMatcher.java
@@ -47,8 +47,6 @@ public class DaoSubscriptionMatcher implements ISubscriptionMatcher {
private Logger ourLog = LoggerFactory.getLogger(DaoSubscriptionMatcher.class);
@Autowired
private FhirContext myCtx;
- @Autowired
- private PlatformTransactionManager myTxManager;
@Override
public InMemoryMatchResult match(CanonicalSubscription theSubscription, ResourceModifiedMessage theMsg) {
@@ -78,10 +76,7 @@ public class DaoSubscriptionMatcher implements ISubscriptionMatcher {
IFhirResourceDao extends IBaseResource> responseDao = myDaoRegistry.getResourceDao(responseResourceDef.getImplementingClass());
responseCriteriaUrl.setLoadSynchronousUpTo(1);
- TransactionTemplate txTemplate = new TransactionTemplate(myTxManager);
- txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
- return txTemplate.execute(t -> responseDao.search(responseCriteriaUrl));
-
+ return responseDao.search(responseCriteriaUrl);
}
}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionActivatingSubscriber.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionActivatingSubscriber.java
index 8f35ce3b196..f442c873211 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionActivatingSubscriber.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionActivatingSubscriber.java
@@ -57,8 +57,6 @@ import javax.annotation.Nonnull;
public class SubscriptionActivatingSubscriber extends BaseSubscriberForSubscriptionResources implements MessageHandler {
private Logger ourLog = LoggerFactory.getLogger(SubscriptionActivatingSubscriber.class);
@Autowired
- private PlatformTransactionManager myTransactionManager;
- @Autowired
private SubscriptionRegistry mySubscriptionRegistry;
@Autowired
private DaoRegistry myDaoRegistry;
@@ -150,13 +148,7 @@ public class SubscriptionActivatingSubscriber extends BaseSubscriberForSubscript
}
private void activateAndRegisterSubscriptionIfRequiredInTransaction(IBaseResource theSubscription) {
- TransactionTemplate txTemplate = new TransactionTemplate(myTransactionManager);
- txTemplate.execute(new TransactionCallbackWithoutResult() {
- @Override
- protected void doInTransactionWithoutResult(@Nonnull TransactionStatus theStatus) {
- activateOrRegisterSubscriptionIfRequired(theSubscription);
- }
- });
+ activateOrRegisterSubscriptionIfRequired(theSubscription);
}
}
diff --git a/hapi-fhir-jpaserver-subscription/src/test/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/DaoSubscriptionMatcherTest.java b/hapi-fhir-jpaserver-subscription/src/test/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/DaoSubscriptionMatcherTest.java
new file mode 100644
index 00000000000..4d2bc26a60f
--- /dev/null
+++ b/hapi-fhir-jpaserver-subscription/src/test/java/ca/uhn/fhir/jpa/subscription/process/matcher/matching/DaoSubscriptionMatcherTest.java
@@ -0,0 +1,75 @@
+package ca.uhn.fhir.jpa.subscription.process.matcher.matching;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.context.support.IValidationSupport;
+import ca.uhn.fhir.interceptor.api.IInterceptorService;
+import ca.uhn.fhir.jpa.api.config.DaoConfig;
+import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
+import ca.uhn.fhir.jpa.model.entity.ModelConfig;
+import ca.uhn.fhir.jpa.model.sched.ISchedulerService;
+import ca.uhn.fhir.jpa.searchparam.config.SearchParamConfig;
+import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamProvider;
+import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionChannelFactory;
+import ca.uhn.fhir.jpa.subscription.process.config.SubscriptionProcessorConfig;
+import ca.uhn.fhir.jpa.subscription.submit.config.SubscriptionSubmitterConfig;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.transaction.PlatformTransactionManager;
+
+import static org.junit.Assert.*;
+
+@RunWith(SpringRunner.class)
+@ContextConfiguration(classes = {
+ SubscriptionProcessorConfig.class,
+ SearchParamConfig.class,
+ DaoSubscriptionMatcherTest.MyConfig.class
+})
+public class DaoSubscriptionMatcherTest {
+
+ @Autowired(required = false)
+ private PlatformTransactionManager myTxManager;
+ @Autowired
+ private DaoSubscriptionMatcher mySvc;
+ @MockBean
+ private ModelConfig myModelConfig;
+ @MockBean
+ private DaoConfig myDaoConfig;
+ @MockBean
+ private ISearchParamProvider mySearchParamProvider;
+ @MockBean
+ private ISchedulerService mySchedulerService;
+ @MockBean
+ private IInterceptorService myInterceptorService;
+ @MockBean
+ private DaoRegistry myDaoRegistry;
+ @MockBean
+ private IValidationSupport myValidationSupport;
+ @MockBean
+ private SubscriptionChannelFactory mySubscriptionChannelFactory;
+
+ /**
+ * Make sure that if we're only running the {@link SubscriptionSubmitterConfig}, we don't need
+ * a transaction manager
+ */
+ @Test
+ public void testSubmitterCanRunWithoutTransactionManager() {
+ assertNull(myTxManager);
+ }
+
+ @Configuration
+ public static class MyConfig {
+
+ @Bean
+ public FhirContext fhirContext() {
+ return FhirContext.forR4();
+ }
+
+ }
+
+}
From 0a28c0c0609cb1a96fdec73a4205acf6a72c41b8 Mon Sep 17 00:00:00 2001
From: jamesagnew
Date: Sun, 5 Apr 2020 07:21:05 -0400
Subject: [PATCH 09/20] Work on subscription cleanup
---
.../subscription/SubscriptionTestUtil.java | 2 +-
.../SubscriptionChannelFactory.java | 4 ++
.../SubscriptionChannelRegistry.java | 51 +++++++++----------
.../SubscriptionWebsocketHandler.java | 4 +-
.../SubscriptionMatchingSubscriber.java | 10 ++--
.../SubscriptionChannelRegistryTest.java | 8 +--
6 files changed, 39 insertions(+), 40 deletions(-)
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/SubscriptionTestUtil.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/SubscriptionTestUtil.java
index 9dbf6fa3492..a286b3729a3 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/SubscriptionTestUtil.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/SubscriptionTestUtil.java
@@ -81,7 +81,7 @@ public class SubscriptionTestUtil {
public void setEmailSender(IIdType theIdElement) {
ActiveSubscription activeSubscription = mySubscriptionRegistry.get(theIdElement.getIdPart());
- SubscriptionChannelWithHandlers subscriptionChannelWithHandlers = mySubscriptionChannelRegistry.get(activeSubscription.getChannelName());
+ SubscriptionChannelWithHandlers subscriptionChannelWithHandlers = mySubscriptionChannelRegistry.getDeliveryReceiverChannel(activeSubscription.getChannelName());
SubscriptionDeliveringEmailSubscriber subscriber = (SubscriptionDeliveringEmailSubscriber) subscriptionChannelWithHandlers.getDeliveryHandlerForUnitTest();
subscriber.setEmailSender(myEmailSender);
}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelFactory.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelFactory.java
index 30e207b952e..873cca9be92 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelFactory.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelFactory.java
@@ -38,6 +38,10 @@ public class SubscriptionChannelFactory {
@Autowired
private IQueueChannelFactory mySubscribableChannelFactory;
+ public MessageChannel newDeliverySendingChannel(String theChannelName) {
+ return mySubscribableChannelFactory.getOrCreateSender(theChannelName, ResourceDeliveryMessage.class, getDeliveryChannelConcurrentConsumers());
+ }
+
public SubscribableChannel newDeliveryChannel(String theChannelName) {
SubscribableChannel channel = mySubscribableChannelFactory.getOrCreateReceiver(theChannelName, ResourceDeliveryMessage.class, getDeliveryChannelConcurrentConsumers());
return new BroadcastingSubscribableChannelWrapper(channel);
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelRegistry.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelRegistry.java
index 1661d132573..62b4b2d00d6 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelRegistry.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelRegistry.java
@@ -20,7 +20,6 @@ package ca.uhn.fhir.jpa.subscription.channel.subscription;
* #L%
*/
-import ca.uhn.fhir.jpa.model.entity.ModelConfig;
import ca.uhn.fhir.jpa.subscription.process.registry.ActiveSubscription;
import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionRegistry;
import com.google.common.annotations.VisibleForTesting;
@@ -29,46 +28,48 @@ import com.google.common.collect.MultimapBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.SubscribableChannel;
import java.util.Collection;
+import java.util.Map;
import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
public class SubscriptionChannelRegistry {
private static final Logger ourLog = LoggerFactory.getLogger(SubscriptionRegistry.class);
- private final SubscriptionChannelCache mySubscriptionChannelCache = new SubscriptionChannelCache();
+ private final SubscriptionChannelCache myDeliveryReceiverChannels = new SubscriptionChannelCache();
// This map is a reference count so we know to destroy the channel when there are no more active subscriptions using it
// Key Channel Name, Value Subscription Id
private final Multimap myActiveSubscriptionByChannelName = MultimapBuilder.hashKeys().arrayListValues().build();
+ private final Map myChannelNameToSender = new ConcurrentHashMap<>();
@Autowired
private SubscriptionDeliveryHandlerFactory mySubscriptionDeliveryHandlerFactory;
@Autowired
private SubscriptionChannelFactory mySubscriptionDeliveryChannelFactory;
- @Autowired
- private ModelConfig myModelConfig;
public synchronized void add(ActiveSubscription theActiveSubscription) {
String channelName = theActiveSubscription.getChannelName();
ourLog.info("Adding subscription {} to channel {}", theActiveSubscription.getId(), channelName);
myActiveSubscriptionByChannelName.put(channelName, theActiveSubscription.getId());
- if (mySubscriptionChannelCache.containsKey(channelName)) {
+ if (myDeliveryReceiverChannels.containsKey(channelName)) {
ourLog.info("Channel {} already exists. Not creating.", channelName);
return;
}
- SubscribableChannel deliveryChannel;
- Optional deliveryHandler;
-
- deliveryChannel = mySubscriptionDeliveryChannelFactory.newDeliveryChannel(channelName);
- deliveryHandler = mySubscriptionDeliveryHandlerFactory.createDeliveryHandler(theActiveSubscription.getChannelType());
+ SubscribableChannel deliveryChannel = mySubscriptionDeliveryChannelFactory.newDeliveryChannel(channelName);
+ Optional deliveryHandler = mySubscriptionDeliveryHandlerFactory.createDeliveryHandler(theActiveSubscription.getChannelType());
SubscriptionChannelWithHandlers subscriptionChannelWithHandlers = new SubscriptionChannelWithHandlers(channelName, deliveryChannel);
deliveryHandler.ifPresent(subscriptionChannelWithHandlers::addHandler);
- mySubscriptionChannelCache.put(channelName, subscriptionChannelWithHandlers);
+ myDeliveryReceiverChannels.put(channelName, subscriptionChannelWithHandlers);
+
+ MessageChannel sendingChannel = mySubscriptionDeliveryChannelFactory.newDeliverySendingChannel(channelName);
+ myChannelNameToSender.put(channelName, sendingChannel);
}
public synchronized void remove(ActiveSubscription theActiveSubscription) {
@@ -81,31 +82,25 @@ public class SubscriptionChannelRegistry {
// This was the last one. Close and remove the channel
if (!myActiveSubscriptionByChannelName.containsKey(channelName)) {
- SubscriptionChannelWithHandlers channel = mySubscriptionChannelCache.get(channelName);
+ SubscriptionChannelWithHandlers channel = myDeliveryReceiverChannels.get(channelName);
if (channel != null) {
channel.close();
}
- mySubscriptionChannelCache.closeAndRemove(channelName);
+ myDeliveryReceiverChannels.closeAndRemove(channelName);
}
+
+ myChannelNameToSender.remove(channelName);
}
- public synchronized SubscriptionChannelWithHandlers get(String theChannelName) {
- return mySubscriptionChannelCache.get(theChannelName);
+ public synchronized SubscriptionChannelWithHandlers getDeliveryReceiverChannel(String theChannelName) {
+ return myDeliveryReceiverChannels.get(theChannelName);
+ }
+
+ public synchronized MessageChannel getDeliverySenderChannel(String theChannelName) {
+ return myChannelNameToSender.get(theChannelName);
}
public synchronized int size() {
- return mySubscriptionChannelCache.size();
- }
-
- @VisibleForTesting
- public void logForUnitTest() {
- ourLog.info("{} Channels: {}", this, size());
- mySubscriptionChannelCache.logForUnitTest();
- for (String key : myActiveSubscriptionByChannelName.keySet()) {
- Collection list = myActiveSubscriptionByChannelName.get(key);
- for (String value : list) {
- ourLog.info("ActiveSubscriptionByChannelName {}: {}", key, value);
- }
- }
+ return myDeliveryReceiverChannels.size();
}
}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/websocket/SubscriptionWebsocketHandler.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/websocket/SubscriptionWebsocketHandler.java
index e628cdce86e..58d0ebe8a3b 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/websocket/SubscriptionWebsocketHandler.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/websocket/SubscriptionWebsocketHandler.java
@@ -115,13 +115,13 @@ public class SubscriptionWebsocketHandler extends TextWebSocketHandler implement
mySession = theSession;
myActiveSubscription = theActiveSubscription;
- SubscriptionChannelWithHandlers subscriptionChannelWithHandlers = mySubscriptionChannelRegistry.get(theActiveSubscription.getChannelName());
+ SubscriptionChannelWithHandlers subscriptionChannelWithHandlers = mySubscriptionChannelRegistry.getDeliveryReceiverChannel(theActiveSubscription.getChannelName());
subscriptionChannelWithHandlers.addHandler(this);
}
@Override
public void closing() {
- SubscriptionChannelWithHandlers subscriptionChannelWithHandlers = mySubscriptionChannelRegistry.get(myActiveSubscription.getChannelName());
+ SubscriptionChannelWithHandlers subscriptionChannelWithHandlers = mySubscriptionChannelRegistry.getDeliveryReceiverChannel(myActiveSubscription.getChannelName());
subscriptionChannelWithHandlers.removeHandler(this);
}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionMatchingSubscriber.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionMatchingSubscriber.java
index 441ff31b8d2..e987eddfdc0 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionMatchingSubscriber.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionMatchingSubscriber.java
@@ -7,13 +7,13 @@ import ca.uhn.fhir.interceptor.api.Pointcut;
import ca.uhn.fhir.jpa.searchparam.matcher.InMemoryMatchResult;
import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionChannelRegistry;
import ca.uhn.fhir.jpa.subscription.model.CanonicalSubscription;
-import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage;
-import ca.uhn.fhir.jpa.subscription.process.registry.ActiveSubscription;
-import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionRegistry;
-import ca.uhn.fhir.jpa.subscription.process.matcher.matching.ISubscriptionMatcher;
import ca.uhn.fhir.jpa.subscription.model.ResourceDeliveryJsonMessage;
import ca.uhn.fhir.jpa.subscription.model.ResourceDeliveryMessage;
import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedJsonMessage;
+import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage;
+import ca.uhn.fhir.jpa.subscription.process.matcher.matching.ISubscriptionMatcher;
+import ca.uhn.fhir.jpa.subscription.process.registry.ActiveSubscription;
+import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionRegistry;
import ca.uhn.fhir.rest.api.EncodingEnum;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.instance.model.api.IBaseResource;
@@ -189,7 +189,7 @@ public class SubscriptionMatchingSubscriber implements MessageHandler {
private boolean sendToDeliveryChannel(ActiveSubscription nextActiveSubscription, ResourceDeliveryMessage theDeliveryMsg) {
boolean retVal = false;
ResourceDeliveryJsonMessage wrappedMsg = new ResourceDeliveryJsonMessage(theDeliveryMsg);
- MessageChannel deliveryChannel = mySubscriptionChannelRegistry.get(nextActiveSubscription.getChannelName()).getChannel();
+ MessageChannel deliveryChannel = mySubscriptionChannelRegistry.getDeliverySenderChannel(nextActiveSubscription.getChannelName());
if (deliveryChannel != null) {
retVal = true;
trySendToDeliveryChannel(wrappedMsg, deliveryChannel);
diff --git a/hapi-fhir-jpaserver-subscription/src/test/java/ca/uhn/fhir/jpa/subscription/module/channel/SubscriptionChannelRegistryTest.java b/hapi-fhir-jpaserver-subscription/src/test/java/ca/uhn/fhir/jpa/subscription/module/channel/SubscriptionChannelRegistryTest.java
index d16ad8f0a88..7fdbfa36e93 100644
--- a/hapi-fhir-jpaserver-subscription/src/test/java/ca/uhn/fhir/jpa/subscription/module/channel/SubscriptionChannelRegistryTest.java
+++ b/hapi-fhir-jpaserver-subscription/src/test/java/ca/uhn/fhir/jpa/subscription/module/channel/SubscriptionChannelRegistryTest.java
@@ -49,13 +49,13 @@ public class SubscriptionChannelRegistryTest {
cansubB.setIdElement(new IdDt("B"));
ActiveSubscription activeSubscriptionB = new ActiveSubscription(cansubB, TEST_CHANNEL_NAME);
- assertNull(mySubscriptionChannelRegistry.get(TEST_CHANNEL_NAME));
+ assertNull(mySubscriptionChannelRegistry.getDeliveryReceiverChannel(TEST_CHANNEL_NAME));
mySubscriptionChannelRegistry.add(activeSubscriptionA);
- assertNotNull(mySubscriptionChannelRegistry.get(TEST_CHANNEL_NAME));
+ assertNotNull(mySubscriptionChannelRegistry.getDeliveryReceiverChannel(TEST_CHANNEL_NAME));
mySubscriptionChannelRegistry.add(activeSubscriptionB);
mySubscriptionChannelRegistry.remove(activeSubscriptionB);
- assertNotNull(mySubscriptionChannelRegistry.get(TEST_CHANNEL_NAME));
+ assertNotNull(mySubscriptionChannelRegistry.getDeliveryReceiverChannel(TEST_CHANNEL_NAME));
mySubscriptionChannelRegistry.remove(activeSubscriptionA);
- assertNull(mySubscriptionChannelRegistry.get(TEST_CHANNEL_NAME));
+ assertNull(mySubscriptionChannelRegistry.getDeliveryReceiverChannel(TEST_CHANNEL_NAME));
}
}
From d0884663d27024bdd681bdc8a3e9ec32fc4d19f0 Mon Sep 17 00:00:00 2001
From: jamesagnew
Date: Sun, 5 Apr 2020 11:34:47 -0400
Subject: [PATCH 10/20] Work on subscription cleanup
---
.../SubscriptionActivatingSubscriber.java | 25 ++++++-------------
.../SubscriptionRegisteringSubscriber.java | 14 +++++++++--
.../registry/SubscriptionRegistry.java | 8 +++---
.../uhn/test/concurrency/PointcutLatch.java | 18 ++++++-------
4 files changed, 33 insertions(+), 32 deletions(-)
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionActivatingSubscriber.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionActivatingSubscriber.java
index f442c873211..a40495af6c0 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionActivatingSubscriber.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionActivatingSubscriber.java
@@ -20,7 +20,6 @@ package ca.uhn.fhir.jpa.subscription.process.matcher.subscriber;
* #L%
*/
-import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.jpa.api.config.DaoConfig;
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
@@ -31,7 +30,6 @@ import ca.uhn.fhir.jpa.subscription.process.matcher.matching.SubscriptionStrateg
import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionCanonicalizer;
import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionConstants;
import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionRegistry;
-import ca.uhn.fhir.model.dstu2.valueset.ResourceTypeEnum;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.util.SubscriptionUtil;
import org.hl7.fhir.instance.model.api.IBaseResource;
@@ -41,10 +39,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.MessagingException;
-import org.springframework.transaction.PlatformTransactionManager;
-import org.springframework.transaction.TransactionStatus;
-import org.springframework.transaction.support.TransactionCallbackWithoutResult;
-import org.springframework.transaction.support.TransactionTemplate;
import javax.annotation.Nonnull;
@@ -113,12 +107,15 @@ public class SubscriptionActivatingSubscriber extends BaseSubscriberForSubscript
if (SubscriptionConstants.REQUESTED_STATUS.equals(statusString)) {
return activateSubscription(theSubscription);
- } else if (SubscriptionConstants.ACTIVE_STATUS.equals(statusString)) {
- return mySubscriptionRegistry.registerSubscriptionUnlessAlreadyRegistered(theSubscription);
- } else {
- // Status isn't "active" or "requested"
- return mySubscriptionRegistry.unregisterSubscriptionIfRegistered(theSubscription, statusString);
+ // FIXME: remove
+// } else if (SubscriptionConstants.ACTIVE_STATUS.equals(statusString)) {
+// return mySubscriptionRegistry.registerSubscriptionUnlessAlreadyRegistered(theSubscription);
+// } else {
+// Status isn't "active" or "requested"
+// return mySubscriptionRegistry.unregisterSubscriptionIfRegistered(theSubscription, statusString);
}
+
+ return false;
}
@SuppressWarnings("unchecked")
@@ -141,12 +138,6 @@ public class SubscriptionActivatingSubscriber extends BaseSubscriberForSubscript
}
}
-
- private boolean isSubscription(IBaseResource theNewResource) {
- RuntimeResourceDefinition resourceDefinition = myFhirContext.getResourceDefinition(theNewResource);
- return ResourceTypeEnum.SUBSCRIPTION.getCode().equals(resourceDefinition.getName());
- }
-
private void activateAndRegisterSubscriptionIfRequiredInTransaction(IBaseResource theSubscription) {
activateOrRegisterSubscriptionIfRequired(theSubscription);
}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionRegisteringSubscriber.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionRegisteringSubscriber.java
index 9c6eabdae79..cd64a0b07b2 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionRegisteringSubscriber.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/SubscriptionRegisteringSubscriber.java
@@ -22,8 +22,10 @@ package ca.uhn.fhir.jpa.subscription.process.matcher.subscriber;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage;
+import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionCanonicalizer;
import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionRegistry;
import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedJsonMessage;
+import org.hl7.fhir.instance.model.api.IBaseResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -45,6 +47,8 @@ public class SubscriptionRegisteringSubscriber extends BaseSubscriberForSubscrip
private FhirContext myFhirContext;
@Autowired
private SubscriptionRegistry mySubscriptionRegistry;
+ @Autowired
+ private SubscriptionCanonicalizer mySubscriptionCanonicalizer;
/**
* Constructor
@@ -68,11 +72,17 @@ public class SubscriptionRegisteringSubscriber extends BaseSubscriberForSubscrip
switch (payload.getOperationType()) {
case DELETE:
- mySubscriptionRegistry.unregisterSubscription(payload.getId(myFhirContext).getIdPart());
+ mySubscriptionRegistry.unregisterSubscriptionIfRegistered(payload.getId(myFhirContext).getIdPart());
break;
case CREATE:
case UPDATE:
- mySubscriptionRegistry.registerSubscriptionUnlessAlreadyRegistered(payload.getNewPayload(myFhirContext));
+ IBaseResource subscription = payload.getNewPayload(myFhirContext);
+ String statusString = mySubscriptionCanonicalizer.getSubscriptionStatus(subscription);
+ if ("active".equals(statusString)) {
+ mySubscriptionRegistry.registerSubscriptionUnlessAlreadyRegistered(payload.getNewPayload(myFhirContext));
+ } else {
+ mySubscriptionRegistry.unregisterSubscriptionIfRegistered(payload.getId(myFhirContext).getIdPart());
+ }
break;
case MANUALLY_TRIGGERED:
default:
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/SubscriptionRegistry.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/SubscriptionRegistry.java
index 26edf6f9a44..0a03f8b11a3 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/SubscriptionRegistry.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/registry/SubscriptionRegistry.java
@@ -104,7 +104,7 @@ public class SubscriptionRegistry {
return canonicalized;
}
- public void unregisterSubscription(String theSubscriptionId) {
+ public void unregisterSubscriptionIfRegistered(String theSubscriptionId) {
Validate.notNull(theSubscriptionId);
ourLog.info("Unregistering active subscription {}", theSubscriptionId);
@@ -126,7 +126,7 @@ public class SubscriptionRegistry {
List idsToDelete = myActiveSubscriptionCache.markAllSubscriptionsNotInCollectionForDeletionAndReturnIdsToDelete(theAllIds);
for (String id : idsToDelete) {
- unregisterSubscription(id);
+ unregisterSubscriptionIfRegistered(id);
}
}
@@ -145,7 +145,7 @@ public class SubscriptionRegistry {
updateSubscription(theSubscription);
return true;
}
- unregisterSubscription(theSubscription.getIdElement().getIdPart());
+ unregisterSubscriptionIfRegistered(theSubscription.getIdElement().getIdPart());
}
if (Subscription.SubscriptionStatus.ACTIVE.equals(newSubscription.getStatus())) {
registerSubscription(theSubscription.getIdElement(), theSubscription);
@@ -177,7 +177,7 @@ public class SubscriptionRegistry {
public boolean unregisterSubscriptionIfRegistered(IBaseResource theSubscription, String theStatusString) {
if (hasSubscription(theSubscription.getIdElement()).isPresent()) {
ourLog.info("Removing {} subscription {}", theStatusString, theSubscription.getIdElement().toUnqualified().getValue());
- unregisterSubscription(theSubscription.getIdElement().getIdPart());
+ unregisterSubscriptionIfRegistered(theSubscription.getIdElement().getIdPart());
return true;
}
return false;
diff --git a/hapi-fhir-test-utilities/src/main/java/ca/uhn/test/concurrency/PointcutLatch.java b/hapi-fhir-test-utilities/src/main/java/ca/uhn/test/concurrency/PointcutLatch.java
index 080b9238903..ed50d5f9469 100644
--- a/hapi-fhir-test-utilities/src/main/java/ca/uhn/test/concurrency/PointcutLatch.java
+++ b/hapi-fhir-test-utilities/src/main/java/ca/uhn/test/concurrency/PointcutLatch.java
@@ -44,7 +44,7 @@ public class PointcutLatch implements IAnonymousInterceptor, IPointcutLatch {
private static final int DEFAULT_TIMEOUT_SECONDS = 10;
private static final FhirObjectPrinter ourFhirObjectToStringMapper = new FhirObjectPrinter();
- private final String name;
+ private final String myName;
private final AtomicLong myLastInvoke = new AtomicLong();
private final AtomicReference myCountdownLatch = new AtomicReference<>();
private final AtomicReference> myFailures = new AtomicReference<>();
@@ -54,13 +54,13 @@ public class PointcutLatch implements IAnonymousInterceptor, IPointcutLatch {
private int myInitialCount;
private boolean myExactMatch;
public PointcutLatch(Pointcut thePointcut) {
- this.name = thePointcut.name();
+ this.myName = thePointcut.name();
myPointcut = thePointcut;
}
public PointcutLatch(String theName) {
- this.name = theName;
+ this.myName = theName;
myPointcut = null;
}
@@ -85,9 +85,9 @@ public class PointcutLatch implements IAnonymousInterceptor, IPointcutLatch {
myExactMatch = theExactMatch;
createLatch(theCount);
if (theExactMatch) {
- ourLog.info("Expecting exactly {} calls to {} latch", theCount, name);
+ ourLog.info("Expecting exactly {} calls to {} latch", theCount, myName);
} else {
- ourLog.info("Expecting at least {} calls to {} latch", theCount, name);
+ ourLog.info("Expecting at least {} calls to {} latch", theCount, myName);
}
}
@@ -111,7 +111,7 @@ public class PointcutLatch implements IAnonymousInterceptor, IPointcutLatch {
}
private String getName() {
- return name + " " + this.getClass().getSimpleName();
+ return myName + " " + this.getClass().getSimpleName();
}
@Override
@@ -175,7 +175,7 @@ public class PointcutLatch implements IAnonymousInterceptor, IPointcutLatch {
CountDownLatch latch = myCountdownLatch.get();
if (myExactMatch) {
if (latch == null) {
- throw new PointcutLatchException("invoke() called outside of setExpectedCount() .. awaitExpected(). Probably got more invocations than expected or clear() was called before invoke() arrived.", theArgs);
+ throw new PointcutLatchException("invoke() for " + myName + " called outside of setExpectedCount() .. awaitExpected(). Probably got more invocations than expected or clear() was called before invoke() arrived with args: " + theArgs, theArgs);
} else if (latch.getCount() <= 0) {
addFailure("invoke() called when countdown was zero.");
}
@@ -186,7 +186,7 @@ public class PointcutLatch implements IAnonymousInterceptor, IPointcutLatch {
if (myCalledWith.get() != null) {
myCalledWith.get().add(theArgs);
}
- ourLog.info("Called {} {} with {}", name, latch, hookParamsToString(theArgs));
+ ourLog.info("Called {} {} with {}", myName, latch, hookParamsToString(theArgs));
latch.countDown();
}
@@ -198,7 +198,7 @@ public class PointcutLatch implements IAnonymousInterceptor, IPointcutLatch {
@Override
public String toString() {
return new ToStringBuilder(this)
- .append("name", name)
+ .append("name", myName)
.append("myCountdownLatch", myCountdownLatch)
// .append("myFailures", myFailures)
// .append("myCalledWith", myCalledWith)
From 40d0c27ae3d743909595fab45a50c4f8143c8b29 Mon Sep 17 00:00:00 2001
From: jamesagnew
Date: Sun, 5 Apr 2020 18:43:27 -0400
Subject: [PATCH 11/20] Work on subscription cleanup
---
.../ca/uhn/fhir/jpa/api/dao/DaoRegistry.java | 8 ++
.../r4/BaseResourceProviderR4Test.java | 1 -
.../r5/BaseResourceProviderR5Test.java | 1 -
.../config/SubscriptionChannelConfig.java | 6 +-
.../SubscriptionChannelFactory.java | 50 +++++++----
.../SubscriptionChannelRegistry.java | 2 +-
.../process/deliver/DaoResourceRetriever.java | 20 ++++-
...aseSubscriberForSubscriptionResources.java | 7 +-
.../MatchingQueueSubscriberLoader.java | 7 +-
.../SubscriptionMatcherInterceptor.java | 15 +++-
.../SubscriptionSubmitInterceptorLoader.java | 1 -
...onfig.java => SubscriptionTestConfig.java} | 6 +-
.../provider/HashMapResourceProvider.java | 70 +++++++++++----
.../provider/HashMapResourceProviderTest.java | 90 ++++++++++++-------
.../uhn/test/concurrency/PointcutLatch.java | 11 ++-
15 files changed, 211 insertions(+), 84 deletions(-)
rename hapi-fhir-jpaserver-subscription/src/test/java/ca/uhn/fhir/jpa/subscription/module/{SubscriptionConfig.java => SubscriptionTestConfig.java} (90%)
diff --git a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/DaoRegistry.java b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/DaoRegistry.java
index 1a0e12bb6e8..d0c26ad60f3 100644
--- a/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/DaoRegistry.java
+++ b/hapi-fhir-jpaserver-api/src/main/java/ca/uhn/fhir/jpa/api/dao/DaoRegistry.java
@@ -51,7 +51,15 @@ public class DaoRegistry implements ApplicationContextAware, IDaoRegistry {
* Constructor
*/
public DaoRegistry() {
+ this(null);
+ }
+
+ /**
+ * Constructor
+ */
+ public DaoRegistry(FhirContext theFhirContext) {
super();
+ myContext = theFhirContext;
}
public void setSupportedResourceTypes(Collection theSupportedResourceTypes) {
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/BaseResourceProviderR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/BaseResourceProviderR4Test.java
index 3558f486ebd..dc45df8c348 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/BaseResourceProviderR4Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/BaseResourceProviderR4Test.java
@@ -163,7 +163,6 @@ public abstract class BaseResourceProviderR4Test extends BaseJpaR4Test {
mySearchCoordinatorSvc = wac.getBean(ISearchCoordinatorSvc.class);
ourSearchParamRegistry = wac.getBean(SearchParamRegistryImpl.class);
ourSubscriptionMatcherInterceptor = wac.getBean(SubscriptionMatcherInterceptor.class);
- ourSubscriptionMatcherInterceptor.start();
confProvider.setSearchParamRegistry(ourSearchParamRegistry);
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r5/BaseResourceProviderR5Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r5/BaseResourceProviderR5Test.java
index aef1545bb36..fb3c410147f 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r5/BaseResourceProviderR5Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r5/BaseResourceProviderR5Test.java
@@ -166,7 +166,6 @@ public abstract class BaseResourceProviderR5Test extends BaseJpaR5Test {
mySearchCoordinatorSvc = wac.getBean(ISearchCoordinatorSvc.class);
ourSearchParamRegistry = wac.getBean(SearchParamRegistryImpl.class);
ourSubscriptionMatcherInterceptor = wac.getBean(SubscriptionMatcherInterceptor.class);
- ourSubscriptionMatcherInterceptor.start();
myFhirCtx.getRestfulClientFactory().setSocketTimeout(5000000);
confProvider.setSearchParamRegistry(ourSearchParamRegistry);
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/config/SubscriptionChannelConfig.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/config/SubscriptionChannelConfig.java
index 64d9c62d8a9..cad03f33097 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/config/SubscriptionChannelConfig.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/config/SubscriptionChannelConfig.java
@@ -33,13 +33,13 @@ public class SubscriptionChannelConfig {
* Create a @Primary @Bean if you need a different implementation
*/
@Bean
- public IQueueChannelFactory subscribableChannelFactory() {
+ public IQueueChannelFactory queueChannelFactory() {
return new LinkedBlockingQueueChannelFactory();
}
@Bean
- public SubscriptionChannelFactory subscriptionChannelFactory() {
- return new SubscriptionChannelFactory();
+ public SubscriptionChannelFactory subscriptionChannelFactory(IQueueChannelFactory theQueueChannelFactory) {
+ return new SubscriptionChannelFactory(theQueueChannelFactory);
}
}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelFactory.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelFactory.java
index 873cca9be92..3603fbd8f23 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelFactory.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelFactory.java
@@ -21,11 +21,13 @@ package ca.uhn.fhir.jpa.subscription.channel.subscription;
*/
import ca.uhn.fhir.jpa.subscription.channel.queue.IQueueChannelFactory;
-import ca.uhn.fhir.jpa.subscription.model.ResourceDeliveryMessage;
-import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage;
+import ca.uhn.fhir.jpa.subscription.model.ResourceDeliveryJsonMessage;
+import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedJsonMessage;
import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionConstants;
+import org.apache.commons.lang3.Validate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
@@ -35,24 +37,32 @@ import org.springframework.messaging.support.AbstractSubscribableChannel;
public class SubscriptionChannelFactory {
- @Autowired
- private IQueueChannelFactory mySubscribableChannelFactory;
+ private static final Logger ourLog = LoggerFactory.getLogger(SubscriptionChannelFactory.class);
+ private final IQueueChannelFactory myQueueChannelFactory;
+
+ /**
+ * Constructor
+ */
+ public SubscriptionChannelFactory(IQueueChannelFactory theQueueChannelFactory) {
+ Validate.notNull(theQueueChannelFactory);
+ myQueueChannelFactory = theQueueChannelFactory;
+ }
public MessageChannel newDeliverySendingChannel(String theChannelName) {
- return mySubscribableChannelFactory.getOrCreateSender(theChannelName, ResourceDeliveryMessage.class, getDeliveryChannelConcurrentConsumers());
+ return myQueueChannelFactory.getOrCreateSender(theChannelName, ResourceDeliveryJsonMessage.class, getDeliveryChannelConcurrentConsumers());
}
public SubscribableChannel newDeliveryChannel(String theChannelName) {
- SubscribableChannel channel = mySubscribableChannelFactory.getOrCreateReceiver(theChannelName, ResourceDeliveryMessage.class, getDeliveryChannelConcurrentConsumers());
+ SubscribableChannel channel = myQueueChannelFactory.getOrCreateReceiver(theChannelName, ResourceDeliveryJsonMessage.class, getDeliveryChannelConcurrentConsumers());
return new BroadcastingSubscribableChannelWrapper(channel);
}
public MessageChannel newMatchingSendingChannel(String theChannelName) {
- return mySubscribableChannelFactory.getOrCreateSender(theChannelName, ResourceModifiedMessage.class, getMatchingChannelConcurrentConsumers());
+ return myQueueChannelFactory.getOrCreateSender(theChannelName, ResourceModifiedJsonMessage.class, getMatchingChannelConcurrentConsumers());
}
public SubscribableChannel newMatchingReceivingChannel(String theChannelName) {
- SubscribableChannel channel = mySubscribableChannelFactory.getOrCreateReceiver(theChannelName, ResourceModifiedMessage.class, getMatchingChannelConcurrentConsumers());
+ SubscribableChannel channel = myQueueChannelFactory.getOrCreateReceiver(theChannelName, ResourceModifiedJsonMessage.class, getMatchingChannelConcurrentConsumers());
return new BroadcastingSubscribableChannelWrapper(channel);
}
@@ -64,8 +74,7 @@ public class SubscriptionChannelFactory {
return SubscriptionConstants.MATCHING_CHANNEL_CONCURRENT_CONSUMERS;
}
-
- private static class BroadcastingSubscribableChannelWrapper extends AbstractSubscribableChannel implements MessageHandler, DisposableBean {
+ public static class BroadcastingSubscribableChannelWrapper extends AbstractSubscribableChannel implements MessageHandler, DisposableBean {
private final SubscribableChannel myWrappedChannel;
@@ -74,13 +83,21 @@ public class SubscriptionChannelFactory {
myWrappedChannel = theChannel;
}
+ public SubscribableChannel getWrappedChannel() {
+ return myWrappedChannel;
+ }
@Override
protected boolean sendInternal(Message> theMessage, long timeout) {
- for (MessageHandler next : getSubscribers()) {
- next.handleMessage(theMessage);
- }
- return true;
+// try {
+ for (MessageHandler next : getSubscribers()) {
+ next.handleMessage(theMessage);
+ }
+ return true;
+// } catch (Exception e) {
+// ourLog.error("Failiure handling message", e);
+// return false;
+// }
}
@Override
@@ -94,7 +111,6 @@ public class SubscriptionChannelFactory {
((DisposableBean) myWrappedChannel).destroy();
}
}
+
}
-
-
}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelRegistry.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelRegistry.java
index 62b4b2d00d6..d5bffd1cb5c 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelRegistry.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelRegistry.java
@@ -87,9 +87,9 @@ public class SubscriptionChannelRegistry {
channel.close();
}
myDeliveryReceiverChannels.closeAndRemove(channelName);
+ myChannelNameToSender.remove(channelName);
}
- myChannelNameToSender.remove(channelName);
}
public synchronized SubscriptionChannelWithHandlers getDeliveryReceiverChannel(String theChannelName) {
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/DaoResourceRetriever.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/DaoResourceRetriever.java
index 0b7721be732..2b7d740841a 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/DaoResourceRetriever.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/DaoResourceRetriever.java
@@ -26,6 +26,7 @@ import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.subscription.process.registry.ActiveSubscription;
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
+import ca.uhn.fhir.util.FhirTerser;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.slf4j.Logger;
@@ -35,10 +36,25 @@ import org.springframework.beans.factory.annotation.Autowired;
public class DaoResourceRetriever implements IResourceRetriever {
private static final Logger ourLog = LoggerFactory.getLogger(ActiveSubscription.class);
+ /**
+ * Constructor
+ */
+ public DaoResourceRetriever() {
+ super();
+ }
+
+ /**
+ * Constructor
+ */
+ public DaoResourceRetriever(FhirContext theFhirContext, DaoRegistry theDaoRegistry) {
+ myFhirContext = theFhirContext;
+ myDaoRegistry = theDaoRegistry;
+ }
+
@Autowired
- FhirContext myFhirContext;
+ private FhirContext myFhirContext;
@Autowired
- DaoRegistry myDaoRegistry;
+ private DaoRegistry myDaoRegistry;
@Override
public IBaseResource getResource(IIdType payloadId) throws ResourceGoneException {
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/BaseSubscriberForSubscriptionResources.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/BaseSubscriberForSubscriptionResources.java
index f1544848335..730296ab0f8 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/BaseSubscriberForSubscriptionResources.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/BaseSubscriberForSubscriptionResources.java
@@ -23,18 +23,21 @@ package ca.uhn.fhir.jpa.subscription.process.matcher.subscriber;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage;
import ca.uhn.fhir.model.dstu2.valueset.ResourceTypeEnum;
+import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.MessageHandler;
+import static org.apache.commons.lang3.StringUtils.isBlank;
+
public abstract class BaseSubscriberForSubscriptionResources implements MessageHandler {
@Autowired
protected FhirContext myFhirContext;
protected boolean isSubscription(ResourceModifiedMessage theNewResource) {
- IIdType payloadId = theNewResource.getId(myFhirContext);
- String payloadIdType = payloadId.getResourceType();
+ IBaseResource payload = theNewResource.getNewPayload(myFhirContext);
+ String payloadIdType = myFhirContext.getResourceDefinition(payload).getName();
return payloadIdType.equals(ResourceTypeEnum.SUBSCRIPTION.getCode());
}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/MatchingQueueSubscriberLoader.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/MatchingQueueSubscriberLoader.java
index 82202cb777f..ddb73db0863 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/MatchingQueueSubscriberLoader.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/MatchingQueueSubscriberLoader.java
@@ -4,6 +4,9 @@ import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionChannelFact
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.event.ContextRefreshedEvent;
+import org.springframework.context.event.ContextStartedEvent;
+import org.springframework.context.event.EventListener;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.SubscribableChannel;
@@ -46,8 +49,8 @@ public class MatchingQueueSubscriberLoader {
protected SubscribableChannel myMatchingChannel;
- @PostConstruct
- public void start() {
+ @EventListener(classes = {ContextRefreshedEvent.class})
+ public void handleContextRefreshEvent() {
if (myMatchingChannel == null) {
myMatchingChannel = mySubscriptionChannelFactory.newMatchingReceivingChannel(SUBSCRIPTION_MATCHING_CHANNEL_NAME);
}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionMatcherInterceptor.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionMatcherInterceptor.java
index 0877bc1f4c5..49b6c74380d 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionMatcherInterceptor.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionMatcherInterceptor.java
@@ -20,6 +20,8 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.event.ContextRefreshedEvent;
+import org.springframework.context.event.EventListener;
import org.springframework.messaging.MessageChannel;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;
@@ -56,7 +58,7 @@ public class SubscriptionMatcherInterceptor implements IResourceModifiedConsumer
@Autowired
private SubscriptionChannelFactory mySubscriptionChannelFactory;
- private MessageChannel myMatchingChannel;
+ private volatile MessageChannel myMatchingChannel;
/**
* Constructor
@@ -65,23 +67,28 @@ public class SubscriptionMatcherInterceptor implements IResourceModifiedConsumer
super();
}
- @PostConstruct
- public void start() {
- myMatchingChannel = mySubscriptionChannelFactory.newMatchingSendingChannel(SubscriptionMatchingSubscriber.SUBSCRIPTION_MATCHING_CHANNEL_NAME);
+ @EventListener(classes = {ContextRefreshedEvent.class})
+ public void startIfNeeded() {
+ if (myMatchingChannel == null) {
+ myMatchingChannel = mySubscriptionChannelFactory.newMatchingSendingChannel(SubscriptionMatchingSubscriber.SUBSCRIPTION_MATCHING_CHANNEL_NAME);
+ }
}
@Hook(Pointcut.STORAGE_PRECOMMIT_RESOURCE_CREATED)
public void resourceCreated(IBaseResource theResource, RequestDetails theRequest) {
+ startIfNeeded();
submitResourceModified(theResource, ResourceModifiedMessage.OperationTypeEnum.CREATE, theRequest);
}
@Hook(Pointcut.STORAGE_PRECOMMIT_RESOURCE_DELETED)
public void resourceDeleted(IBaseResource theResource, RequestDetails theRequest) {
+ startIfNeeded();
submitResourceModified(theResource, ResourceModifiedMessage.OperationTypeEnum.DELETE, theRequest);
}
@Hook(Pointcut.STORAGE_PRECOMMIT_RESOURCE_UPDATED)
public void resourceUpdated(IBaseResource theOldResource, IBaseResource theNewResource, RequestDetails theRequest) {
+ startIfNeeded();
submitResourceModified(theNewResource, ResourceModifiedMessage.OperationTypeEnum.UPDATE, theRequest);
}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionSubmitInterceptorLoader.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionSubmitInterceptorLoader.java
index a827abc7462..72814d0e088 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionSubmitInterceptorLoader.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/submit/interceptor/SubscriptionSubmitInterceptorLoader.java
@@ -53,7 +53,6 @@ public class SubscriptionSubmitInterceptorLoader {
if (supportedSubscriptionTypes.isEmpty()) {
ourLog.info("Subscriptions are disabled on this server. Subscriptions will not be activated and incoming resources will not be matched against subscriptions.");
} else {
- mySubscriptionMatcherInterceptor.start();
ourLog.info("Registering subscription matcher interceptor");
myInterceptorRegistry.registerInterceptor(mySubscriptionMatcherInterceptor);
}
diff --git a/hapi-fhir-jpaserver-subscription/src/test/java/ca/uhn/fhir/jpa/subscription/module/SubscriptionConfig.java b/hapi-fhir-jpaserver-subscription/src/test/java/ca/uhn/fhir/jpa/subscription/module/SubscriptionTestConfig.java
similarity index 90%
rename from hapi-fhir-jpaserver-subscription/src/test/java/ca/uhn/fhir/jpa/subscription/module/SubscriptionConfig.java
rename to hapi-fhir-jpaserver-subscription/src/test/java/ca/uhn/fhir/jpa/subscription/module/SubscriptionTestConfig.java
index 2e3589d9116..21b31aaeb13 100644
--- a/hapi-fhir-jpaserver-subscription/src/test/java/ca/uhn/fhir/jpa/subscription/module/SubscriptionConfig.java
+++ b/hapi-fhir-jpaserver-subscription/src/test/java/ca/uhn/fhir/jpa/subscription/module/SubscriptionTestConfig.java
@@ -37,7 +37,7 @@ import org.springframework.scheduling.annotation.EnableScheduling;
@Configuration
@Import({SearchParamConfig.class})
@EnableScheduling
-public class SubscriptionConfig {
+public class SubscriptionTestConfig {
@Autowired
private FhirContext myFhirContext;
@@ -54,8 +54,8 @@ public class SubscriptionConfig {
}
@Bean
- public SubscriptionChannelFactory subscriptionChannelFactory() {
- return new SubscriptionChannelFactory();
+ public SubscriptionChannelFactory subscriptionChannelFactory(IQueueChannelFactory theQueueChannelFactory) {
+ return new SubscriptionChannelFactory(theQueueChannelFactory);
}
diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/provider/HashMapResourceProvider.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/provider/HashMapResourceProvider.java
index 2780e3c2da5..8b8d5097de7 100644
--- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/provider/HashMapResourceProvider.java
+++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/provider/HashMapResourceProvider.java
@@ -31,7 +31,11 @@ import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.rest.annotation.*;
import ca.uhn.fhir.rest.api.MethodOutcome;
-import ca.uhn.fhir.rest.api.server.*;
+import ca.uhn.fhir.rest.api.server.IPreResourceAccessDetails;
+import ca.uhn.fhir.rest.api.server.IPreResourceShowDetails;
+import ca.uhn.fhir.rest.api.server.RequestDetails;
+import ca.uhn.fhir.rest.api.server.SimplePreResourceAccessDetails;
+import ca.uhn.fhir.rest.api.server.SimplePreResourceShowDetails;
import ca.uhn.fhir.rest.param.TokenAndListParam;
import ca.uhn.fhir.rest.param.TokenOrListParam;
import ca.uhn.fhir.rest.param.TokenParam;
@@ -48,7 +52,13 @@ import org.hl7.fhir.instance.model.api.IPrimitiveType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicLong;
import static org.apache.commons.lang3.StringUtils.isBlank;
@@ -119,8 +129,8 @@ public class HashMapResourceProvider implements IResour
}
@Create
- public MethodOutcome create(@ResourceParam T theResource) {
- createInternal(theResource);
+ public MethodOutcome create(@ResourceParam T theResource, RequestDetails theRequestDetails) {
+ createInternal(theResource, theRequestDetails);
myCreateCount.incrementAndGet();
@@ -130,17 +140,17 @@ public class HashMapResourceProvider implements IResour
.setId(theResource.getIdElement());
}
- private void createInternal(@ResourceParam T theResource) {
+ private void createInternal(@ResourceParam T theResource, RequestDetails theRequestDetails) {
long idPart = myNextId++;
String idPartAsString = Long.toString(idPart);
Long versionIdPart = 1L;
- IIdType id = store(theResource, idPartAsString, versionIdPart);
+ IIdType id = store(theResource, idPartAsString, versionIdPart, theRequestDetails);
theResource.setId(id);
}
@Delete
- public MethodOutcome delete(@IdParam IIdType theId) {
+ public MethodOutcome delete(@IdParam IIdType theId, RequestDetails theRequestDetails) {
TreeMap versions = myIdToVersionToResourceMap.get(theId.getIdPart());
if (versions == null || versions.isEmpty()) {
throw new ResourceNotFoundException(theId);
@@ -148,7 +158,7 @@ public class HashMapResourceProvider implements IResour
long nextVersion = versions.lastEntry().getKey() + 1L;
- IIdType id = store(null, theId.getIdPart(), nextVersion);
+ IIdType id = store(null, theId.getIdPart(), nextVersion, theRequestDetails);
myDeleteCount.incrementAndGet();
@@ -310,7 +320,7 @@ public class HashMapResourceProvider implements IResour
return fireInterceptorsAndFilterAsNeeded(retVal, theRequestDetails);
}
- private IIdType store(@ResourceParam T theResource, String theIdPart, Long theVersionIdPart) {
+ private IIdType store(@ResourceParam T theResource, String theIdPart, Long theVersionIdPart, RequestDetails theRequestDetails) {
IIdType id = myFhirContext.getVersion().newIdType();
String versionIdPart = Long.toString(theVersionIdPart);
id.setParts(null, myResourceName, theIdPart, versionIdPart);
@@ -348,6 +358,35 @@ public class HashMapResourceProvider implements IResour
TreeMap versionToResource = getVersionToResource(theIdPart);
versionToResource.put(theVersionIdPart, theResource);
+ if (theRequestDetails != null) {
+ IInterceptorBroadcaster interceptorBroadcaster = theRequestDetails.getInterceptorBroadcaster();
+
+ if (theResource != null) {
+ if (!myIdToHistory.containsKey(theIdPart)) {
+
+ // Interceptor call: STORAGE_PRESTORAGE_RESOURCE_CREATED
+ HookParams params = new HookParams()
+ .add(RequestDetails.class, theRequestDetails)
+ .addIfMatchesType(ServletRequestDetails.class, theRequestDetails)
+ .add(IBaseResource.class, theResource);
+ interceptorBroadcaster.callHooks(Pointcut.STORAGE_PRESTORAGE_RESOURCE_CREATED, params);
+ interceptorBroadcaster.callHooks(Pointcut.STORAGE_PRECOMMIT_RESOURCE_CREATED, params);
+
+ } else {
+
+ // Interceptor call: STORAGE_PRESTORAGE_RESOURCE_UPDATED
+ HookParams params = new HookParams()
+ .add(RequestDetails.class, theRequestDetails)
+ .addIfMatchesType(ServletRequestDetails.class, theRequestDetails)
+ .add(IBaseResource.class, myIdToHistory.get(theIdPart).getFirst())
+ .add(IBaseResource.class, theResource);
+ interceptorBroadcaster.callHooks(Pointcut.STORAGE_PRESTORAGE_RESOURCE_UPDATED, params);
+ interceptorBroadcaster.callHooks(Pointcut.STORAGE_PRECOMMIT_RESOURCE_UPDATED, params);
+
+ }
+ }
+ }
+
// Store to type history map
myTypeHistory.addFirst(theResource);
@@ -365,11 +404,12 @@ public class HashMapResourceProvider implements IResour
@Update
public MethodOutcome update(
@ResourceParam T theResource,
- @ConditionalUrlParam String theConditional) {
+ @ConditionalUrlParam String theConditional,
+ RequestDetails theRequestDetails) {
ValidateUtil.isTrueOrThrowInvalidRequest(isBlank(theConditional), "This server doesn't support conditional update");
- boolean created = updateInternal(theResource);
+ boolean created = updateInternal(theResource, theRequestDetails);
myUpdateCount.incrementAndGet();
return new MethodOutcome()
@@ -378,7 +418,7 @@ public class HashMapResourceProvider implements IResour
.setId(theResource.getIdElement());
}
- private boolean updateInternal(@ResourceParam T theResource) {
+ private boolean updateInternal(@ResourceParam T theResource, RequestDetails theRequestDetails) {
String idPartAsString = theResource.getIdElement().getIdPart();
TreeMap versionToResource = getVersionToResource(idPartAsString);
@@ -392,7 +432,7 @@ public class HashMapResourceProvider implements IResour
created = false;
}
- IIdType id = store(theResource, idPartAsString, versionIdPart);
+ IIdType id = store(theResource, idPartAsString, versionIdPart, theRequestDetails);
theResource.setId(id);
return created;
}
@@ -411,9 +451,9 @@ public class HashMapResourceProvider implements IResour
*/
public IIdType store(T theResource) {
if (theResource.getIdElement().hasIdPart()) {
- updateInternal(theResource);
+ updateInternal(theResource, null);
} else {
- createInternal(theResource);
+ createInternal(theResource, null);
}
return theResource.getIdElement();
}
diff --git a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/provider/HashMapResourceProviderTest.java b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/provider/HashMapResourceProviderTest.java
index 220b0094db3..d63632d313c 100644
--- a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/provider/HashMapResourceProviderTest.java
+++ b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/provider/HashMapResourceProviderTest.java
@@ -1,6 +1,8 @@
package ca.uhn.fhir.rest.server.provider;
import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.interceptor.api.IAnonymousInterceptor;
+import ca.uhn.fhir.interceptor.api.Pointcut;
import ca.uhn.fhir.rest.client.api.IGenericClient;
import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
import ca.uhn.fhir.rest.gclient.IDeleteTyped;
@@ -8,6 +10,7 @@ import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
+import ca.uhn.fhir.test.utilities.JettyUtil;
import ca.uhn.fhir.util.TestUtil;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
@@ -21,6 +24,10 @@ import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.MockitoJUnitRunner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -28,11 +35,17 @@ import javax.servlet.ServletException;
import java.util.List;
import java.util.stream.Collectors;
-import static org.hamcrest.Matchers.*;
-import static org.junit.Assert.*;
-
-import ca.uhn.fhir.test.utilities.JettyUtil;
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.containsInAnyOrder;
+import static org.hamcrest.Matchers.matchesPattern;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+@RunWith(MockitoJUnitRunner.class)
public class HashMapResourceProviderTest {
private static final Logger ourLog = LoggerFactory.getLogger(HashMapResourceProviderTest.class);
@@ -43,6 +56,9 @@ public class HashMapResourceProviderTest {
private static HashMapResourceProvider myPatientResourceProvider;
private static HashMapResourceProvider myObservationResourceProvider;
+ @Mock
+ private IAnonymousInterceptor myAnonymousInterceptor;
+
@Before
public void before() {
ourRestServer.clearData();
@@ -52,6 +68,9 @@ public class HashMapResourceProviderTest {
@Test
public void testCreateAndRead() {
+ ourRestServer.getInterceptorService().registerAnonymousInterceptor(Pointcut.STORAGE_PRESTORAGE_RESOURCE_CREATED, myAnonymousInterceptor);
+ ourRestServer.getInterceptorService().registerAnonymousInterceptor(Pointcut.STORAGE_PRECOMMIT_RESOURCE_CREATED, myAnonymousInterceptor);
+
// Create
Patient p = new Patient();
p.setActive(true);
@@ -59,6 +78,9 @@ public class HashMapResourceProviderTest {
assertThat(id.getIdPart(), matchesPattern("[0-9]+"));
assertEquals("1", id.getVersionIdPart());
+ verify(myAnonymousInterceptor, Mockito.times(1)).invoke(eq(Pointcut.STORAGE_PRESTORAGE_RESOURCE_CREATED), any());
+ verify(myAnonymousInterceptor, Mockito.times(1)).invoke(eq(Pointcut.STORAGE_PRECOMMIT_RESOURCE_CREATED), any());
+
// Read
p = (Patient) ourClient.read().resource("Patient").withId(id).execute();
assertEquals(true, p.getActive());
@@ -282,6 +304,9 @@ public class HashMapResourceProviderTest {
assertEquals("1", id.getVersionIdPart());
// Update
+ ourRestServer.getInterceptorService().registerAnonymousInterceptor(Pointcut.STORAGE_PRESTORAGE_RESOURCE_UPDATED, myAnonymousInterceptor);
+ ourRestServer.getInterceptorService().registerAnonymousInterceptor(Pointcut.STORAGE_PRECOMMIT_RESOURCE_UPDATED, myAnonymousInterceptor);
+
p = new Patient();
p.setId(id);
p.setActive(false);
@@ -289,6 +314,9 @@ public class HashMapResourceProviderTest {
assertThat(id.getIdPart(), matchesPattern("[0-9]+"));
assertEquals("2", id.getVersionIdPart());
+ verify(myAnonymousInterceptor, Mockito.times(1)).invoke(eq(Pointcut.STORAGE_PRESTORAGE_RESOURCE_UPDATED), any());
+ verify(myAnonymousInterceptor, Mockito.times(1)).invoke(eq(Pointcut.STORAGE_PRECOMMIT_RESOURCE_UPDATED), any());
+
assertEquals(1, myPatientResourceProvider.getCountCreate());
assertEquals(1, myPatientResourceProvider.getCountUpdate());
@@ -305,33 +333,6 @@ public class HashMapResourceProviderTest {
}
}
- @AfterClass
- public static void afterClassClearContext() throws Exception {
- JettyUtil.closeServer(ourListenerServer);
- TestUtil.clearAllStaticFieldsForUnitTest();
- }
-
- @BeforeClass
- public static void startListenerServer() throws Exception {
- ourRestServer = new MyRestfulServer();
-
- ourListenerServer = new Server(0);
-
- ServletContextHandler proxyHandler = new ServletContextHandler();
- proxyHandler.setContextPath("/");
-
- ServletHolder servletHolder = new ServletHolder();
- servletHolder.setServlet(ourRestServer);
- proxyHandler.addServlet(servletHolder, "/*");
-
- ourListenerServer.setHandler(proxyHandler);
- JettyUtil.startServer(ourListenerServer);
- int ourListenerPort = JettyUtil.getPortForStartedServer(ourListenerServer);
- String ourBase = "http://localhost:" + ourListenerPort + "/";
- ourCtx.getRestfulClientFactory().setSocketTimeout(120000);
- ourClient = ourCtx.newRestfulGenericClient(ourBase);
- }
-
private static class MyRestfulServer extends RestfulServer {
MyRestfulServer() {
@@ -359,5 +360,32 @@ public class HashMapResourceProviderTest {
}
+ @AfterClass
+ public static void afterClassClearContext() throws Exception {
+ JettyUtil.closeServer(ourListenerServer);
+ TestUtil.clearAllStaticFieldsForUnitTest();
+ }
+
+ @BeforeClass
+ public static void startListenerServer() throws Exception {
+ ourRestServer = new MyRestfulServer();
+
+ ourListenerServer = new Server(0);
+
+ ServletContextHandler proxyHandler = new ServletContextHandler();
+ proxyHandler.setContextPath("/");
+
+ ServletHolder servletHolder = new ServletHolder();
+ servletHolder.setServlet(ourRestServer);
+ proxyHandler.addServlet(servletHolder, "/*");
+
+ ourListenerServer.setHandler(proxyHandler);
+ JettyUtil.startServer(ourListenerServer);
+ int ourListenerPort = JettyUtil.getPortForStartedServer(ourListenerServer);
+ String ourBase = "http://localhost:" + ourListenerPort + "/";
+ ourCtx.getRestfulClientFactory().setSocketTimeout(120000);
+ ourClient = ourCtx.newRestfulGenericClient(ourBase);
+ }
+
}
diff --git a/hapi-fhir-test-utilities/src/main/java/ca/uhn/test/concurrency/PointcutLatch.java b/hapi-fhir-test-utilities/src/main/java/ca/uhn/test/concurrency/PointcutLatch.java
index ed50d5f9469..e9128ae289a 100644
--- a/hapi-fhir-test-utilities/src/main/java/ca/uhn/test/concurrency/PointcutLatch.java
+++ b/hapi-fhir-test-utilities/src/main/java/ca/uhn/test/concurrency/PointcutLatch.java
@@ -26,6 +26,7 @@ import ca.uhn.fhir.interceptor.api.IAnonymousInterceptor;
import ca.uhn.fhir.interceptor.api.Pointcut;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -47,6 +48,7 @@ public class PointcutLatch implements IAnonymousInterceptor, IPointcutLatch {
private final String myName;
private final AtomicLong myLastInvoke = new AtomicLong();
private final AtomicReference myCountdownLatch = new AtomicReference<>();
+ private final AtomicReference myCountdownLatchSetStacktrace = new AtomicReference<>();
private final AtomicReference> myFailures = new AtomicReference<>();
private final AtomicReference> myCalledWith = new AtomicReference<>();
private final Pointcut myPointcut;
@@ -80,7 +82,8 @@ public class PointcutLatch implements IAnonymousInterceptor, IPointcutLatch {
public void setExpectedCount(int theCount, boolean theExactMatch) {
if (myCountdownLatch.get() != null) {
- throw new PointcutLatchException("setExpectedCount() called before previous awaitExpected() completed.");
+ String previousStack = myCountdownLatchSetStacktrace.get();
+ throw new PointcutLatchException("setExpectedCount() called before previous awaitExpected() completed. Previous set stack:\n" + previousStack);
}
myExactMatch = theExactMatch;
createLatch(theCount);
@@ -99,6 +102,11 @@ public class PointcutLatch implements IAnonymousInterceptor, IPointcutLatch {
myFailures.set(Collections.synchronizedList(new ArrayList<>()));
myCalledWith.set(Collections.synchronizedList(new ArrayList<>()));
myCountdownLatch.set(new CountDownLatch(theCount));
+ try {
+ throw new Exception();
+ } catch (Exception e) {
+ myCountdownLatchSetStacktrace.set(ExceptionUtils.getStackTrace(e));
+ }
myInitialCount = theCount;
}
@@ -151,6 +159,7 @@ public class PointcutLatch implements IAnonymousInterceptor, IPointcutLatch {
@Override
public void clear() {
myCountdownLatch.set(null);
+ myCountdownLatchSetStacktrace.set(null);
}
private String toCalledWithString() {
From b78205c218a1bf5df7661a6dbceb0e184b8085cb Mon Sep 17 00:00:00 2001
From: jamesagnew
Date: Mon, 6 Apr 2020 17:00:45 -0400
Subject: [PATCH 12/20] Ongoing cleanup
---
.../fhir/docs/server_jpa/configuration.md | 2 +-
.../BaseResourceProviderDstu2Test.java | 2 +-
.../dstu3/BaseResourceProviderDstu3Test.java | 2 +-
.../r4/BaseResourceProviderR4Test.java | 2 +-
.../r5/BaseResourceProviderR5Test.java | 2 +-
.../channel/queue/IQueueChannelFactory.java | 30 +-
.../channel/queue/IQueueChannelReceiver.java | 27 ++
.../channel/queue/IQueueChannelSender.java | 28 ++
.../queue/LinkedBlockingQueueChannel.java | 78 +----
.../LinkedBlockingQueueChannelFactory.java | 57 +++-
.../queue/QueueChannelConsumerConfig.java | 35 +++
.../SubscriptionChannelFactory.java | 74 +++--
.../SubscriptionChannelRegistry.java | 4 +-
.../config/SubscriptionProcessorConfig.java | 5 -
.../config/WebsocketDispatcherConfig.java | 11 +-
.../SubscriptionWebsocketHandler.java | 7 +
.../WebsocketConnectionValidator.java | 7 +
...aseSubscriberForSubscriptionResources.java | 16 +-
.../SubscriptionChannelFactoryTest.java | 76 +++++
.../ca/uhn/fhirtest/TestRestfulServer.java | 3 +-
.../ca/uhn/fhirtest/config/CommonConfig.java | 2 +-
...hNarrowingInterceptor.java_703256810379985 | 278 ++++++++++++++++++
.../autoconfigure/FhirAutoConfiguration.java | 1 -
.../uhn/test/concurrency/PointcutLatch.java | 4 +
24 files changed, 609 insertions(+), 144 deletions(-)
create mode 100644 hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/IQueueChannelReceiver.java
create mode 100644 hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/IQueueChannelSender.java
create mode 100644 hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/QueueChannelConsumerConfig.java
rename {hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa => hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process}/config/WebsocketDispatcherConfig.java (87%)
create mode 100644 hapi-fhir-jpaserver-subscription/src/test/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelFactoryTest.java
create mode 100644 hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/SearchNarrowingInterceptor.java_703256810379985
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa/configuration.md b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa/configuration.md
index 25125d85b08..0b33e7c4f52 100644
--- a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa/configuration.md
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa/configuration.md
@@ -56,7 +56,7 @@ web address.
A common use for logical references is in references to conformance resources, such as ValueSets, StructureDefinitions, etc. For example, you might refer to the ValueSet `http://hl7.org/fhir/ValueSet/quantity-comparator` from your own resources. In this case, you are not necessarily telling the server that this is a real address that it should resolve, but rather that this is an identifier for a ValueSet where `ValueSet.url` has the given URI/URL.
-HAPI can be configured to treat certain URI/URL patterns as logical by using the DaoConfig#setTreatReferencesAsLogical property (see [JavaDoc](/hapi-fhir/apidocs/hapi-fhir-jpaserver-base/ca/uhn/fhir/jpa/dao/DaoConfig.html#setTreatReferencesAsLogical(java.util.Set))).
+HAPI can be configured to treat certain URI/URL patterns as logical by using the DaoConfig#setTreatReferencesAsLogical property (see [JavaDoc](/hapi-fhir/apidocs/hapi-fhir-jpaserver-api/ca/uhn/fhir/jpa/api/config/DaoConfig.html#setTreatReferencesAsLogical(java.util.Set))).
For example:
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/BaseResourceProviderDstu2Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/BaseResourceProviderDstu2Test.java
index 93ce55c988d..539d27c2c1b 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/BaseResourceProviderDstu2Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/BaseResourceProviderDstu2Test.java
@@ -1,6 +1,6 @@
package ca.uhn.fhir.jpa.provider;
-import ca.uhn.fhir.jpa.config.WebsocketDispatcherConfig;
+import ca.uhn.fhir.jpa.subscription.process.config.WebsocketDispatcherConfig;
import ca.uhn.fhir.jpa.dao.dstu2.BaseJpaDstu2Test;
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
import ca.uhn.fhir.model.dstu2.resource.Bundle;
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/BaseResourceProviderDstu3Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/BaseResourceProviderDstu3Test.java
index 445a7766ffb..cce16453f54 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/BaseResourceProviderDstu3Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/BaseResourceProviderDstu3Test.java
@@ -1,7 +1,7 @@
package ca.uhn.fhir.jpa.provider.dstu3;
import ca.uhn.fhir.context.support.IValidationSupport;
-import ca.uhn.fhir.jpa.config.WebsocketDispatcherConfig;
+import ca.uhn.fhir.jpa.subscription.process.config.WebsocketDispatcherConfig;
import ca.uhn.fhir.jpa.dao.dstu3.BaseJpaDstu3Test;
import ca.uhn.fhir.jpa.provider.GraphQLProvider;
import ca.uhn.fhir.jpa.provider.SubscriptionTriggeringProvider;
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/BaseResourceProviderR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/BaseResourceProviderR4Test.java
index dc45df8c348..23cd7b33f9d 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/BaseResourceProviderR4Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/BaseResourceProviderR4Test.java
@@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.provider.r4;
import ca.uhn.fhir.context.support.IValidationSupport;
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
-import ca.uhn.fhir.jpa.config.WebsocketDispatcherConfig;
+import ca.uhn.fhir.jpa.subscription.process.config.WebsocketDispatcherConfig;
import ca.uhn.fhir.jpa.dao.r4.BaseJpaR4Test;
import ca.uhn.fhir.jpa.provider.GraphQLProvider;
import ca.uhn.fhir.jpa.provider.TerminologyUploaderProvider;
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r5/BaseResourceProviderR5Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r5/BaseResourceProviderR5Test.java
index fb3c410147f..578da58bc53 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r5/BaseResourceProviderR5Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r5/BaseResourceProviderR5Test.java
@@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.provider.r5;
import ca.uhn.fhir.context.support.IValidationSupport;
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
-import ca.uhn.fhir.jpa.config.WebsocketDispatcherConfig;
+import ca.uhn.fhir.jpa.subscription.process.config.WebsocketDispatcherConfig;
import ca.uhn.fhir.jpa.dao.r5.BaseJpaR5Test;
import ca.uhn.fhir.jpa.provider.GraphQLProvider;
import ca.uhn.fhir.jpa.provider.TerminologyUploaderProvider;
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/IQueueChannelFactory.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/IQueueChannelFactory.java
index 92321b7f44b..9ec88c0e3d6 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/IQueueChannelFactory.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/IQueueChannelFactory.java
@@ -20,10 +20,6 @@ package ca.uhn.fhir.jpa.subscription.channel.queue;
* #L%
*/
-import org.springframework.messaging.MessageChannel;
-import org.springframework.messaging.SubscribableChannel;
-
-
/**
* This interface is the factory for Queue Channels, which are the low level abstraction over a
* queue (e.g. memory queue, JMS queue, Kafka stream, etc.) for any purpose.
@@ -34,20 +30,38 @@ public interface IQueueChannelFactory {
* Create a channel that is used to receive messages from the queue.
*
*
- * Implementations can choose to return the same object for multiple invocations of this method (and {@link #getOrCreateReceiver(String, Class, int)}
+ * Implementations can choose to return the same object for multiple invocations of this method (and {@link #getOrCreateReceiver(String, Class, QueueChannelConsumerConfig)}
* when invoked with the same {@literal theChannelName} if they need to, or they can create a new instance.
*
+ *
+ * @param theChannelName The actual underlying queue name
+ * @param theMessageType The object type that will be placed on this queue. Objects will be Jackson-annotated structures.
+ * @param theConfig Contains the configuration for subscribers. Note that this parameter is provided for
+ * both {@link #getOrCreateReceiver} and
+ * {@link #getOrCreateSender(String, Class, QueueChannelConsumerConfig)}
+ * even though this object is used to configure the sender only. We do this because the factory
+ * may want to create a single object to be used for both the sender and receiver, so this allows
+ * the config details to be known regardless of which method is returned first.
*/
- SubscribableChannel getOrCreateReceiver(String theChannelName, Class> theMessageType, int theConcurrentConsumers);
+ IQueueChannelReceiver getOrCreateReceiver(String theChannelName, Class> theMessageType, QueueChannelConsumerConfig theConfig);
/**
* Create a channel that is used to send messages to the queue.
*
*
- * Implementations can choose to return the same object for multiple invocations of this method (and {@link #getOrCreateReceiver(String, Class, int)}
+ * Implementations can choose to return the same object for multiple invocations of this method (and {@link #getOrCreateReceiver(String, Class, QueueChannelConsumerConfig)}
* when invoked with the same {@literal theChannelName} if they need to, or they can create a new instance.
*
+ *
+ * @param theChannelName The actual underlying queue name
+ * @param theMessageType The object type that will be placed on this queue. Objects will be Jackson-annotated structures.
+ * @param theConfig Contains the configuration for subscribers. Note that this parameter is provided for
+ * both {@link #getOrCreateReceiver} and
+ * {@link #getOrCreateSender(String, Class, QueueChannelConsumerConfig)}
+ * even though this object is used to configure the sender only. We do this because the factory
+ * may want to create a single object to be used for both the sender and receiver, so this allows
+ * the config details to be known regardless of which method is returned first.
*/
- MessageChannel getOrCreateSender(String theChannelName, Class> theMessageType, int theConcurrentConsumers);
+ IQueueChannelSender getOrCreateSender(String theChannelName, Class> theMessageType, QueueChannelConsumerConfig theConfig);
}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/IQueueChannelReceiver.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/IQueueChannelReceiver.java
new file mode 100644
index 00000000000..eca925b288a
--- /dev/null
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/IQueueChannelReceiver.java
@@ -0,0 +1,27 @@
+package ca.uhn.fhir.jpa.subscription.channel.queue;
+
+/*-
+ * #%L
+ * HAPI FHIR Subscription Server
+ * %%
+ * Copyright (C) 2014 - 2020 University Health Network
+ * %%
+ * 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%
+ */
+
+import org.springframework.messaging.SubscribableChannel;
+import org.springframework.messaging.support.InterceptableChannel;
+
+public interface IQueueChannelReceiver extends SubscribableChannel, InterceptableChannel {
+}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/IQueueChannelSender.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/IQueueChannelSender.java
new file mode 100644
index 00000000000..f231347072b
--- /dev/null
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/IQueueChannelSender.java
@@ -0,0 +1,28 @@
+package ca.uhn.fhir.jpa.subscription.channel.queue;
+
+/*-
+ * #%L
+ * HAPI FHIR Subscription Server
+ * %%
+ * Copyright (C) 2014 - 2020 University Health Network
+ * %%
+ * 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%
+ */
+
+import org.springframework.messaging.MessageChannel;
+import org.springframework.messaging.SubscribableChannel;
+import org.springframework.messaging.support.InterceptableChannel;
+
+public interface IQueueChannelSender extends MessageChannel, InterceptableChannel {
+}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/LinkedBlockingQueueChannel.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/LinkedBlockingQueueChannel.java
index 4a8b091fba5..1695ac6a410 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/LinkedBlockingQueueChannel.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/LinkedBlockingQueueChannel.java
@@ -20,84 +20,14 @@ package ca.uhn.fhir.jpa.subscription.channel.queue;
* #L%
*/
-import ca.uhn.fhir.util.StopWatch;
-import com.google.common.annotations.VisibleForTesting;
-import org.apache.commons.lang3.concurrent.BasicThreadFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.messaging.Message;
-import org.springframework.messaging.MessageHandler;
-import org.springframework.messaging.SubscribableChannel;
-import org.springframework.messaging.support.ChannelInterceptor;
import org.springframework.messaging.support.ExecutorSubscribableChannel;
-import java.util.ArrayList;
-import java.util.concurrent.*;
+import java.util.concurrent.ThreadPoolExecutor;
-public class LinkedBlockingQueueChannel implements SubscribableChannel {
- private Logger ourLog = LoggerFactory.getLogger(LinkedBlockingQueueChannel.class);
+public class LinkedBlockingQueueChannel extends ExecutorSubscribableChannel implements IQueueChannelSender, IQueueChannelReceiver {
- private final ExecutorSubscribableChannel mySubscribableChannel;
- private final BlockingQueue myQueue;
-
- public LinkedBlockingQueueChannel(BlockingQueue theQueue, String theThreadNamingPattern, int theConcurrentConsumers) {
-
- ThreadFactory threadFactory = new BasicThreadFactory.Builder()
- .namingPattern(theThreadNamingPattern)
- .daemon(false)
- .priority(Thread.NORM_PRIORITY)
- .build();
- RejectedExecutionHandler rejectedExecutionHandler = (theRunnable, theExecutor) -> {
- ourLog.info("Note: Executor queue is full ({} elements), waiting for a slot to become available!", theQueue.size());
- StopWatch sw = new StopWatch();
- try {
- theQueue.put(theRunnable);
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- throw new RejectedExecutionException("Task " + theRunnable.toString() +
- " rejected from " + e.toString());
- }
- ourLog.info("Slot become available after {}ms", sw.getMillis());
- };
- ThreadPoolExecutor executor = new ThreadPoolExecutor(
- 1,
- theConcurrentConsumers,
- 0L,
- TimeUnit.MILLISECONDS,
- theQueue,
- threadFactory,
- rejectedExecutionHandler);
- myQueue = theQueue;
- mySubscribableChannel = new ExecutorSubscribableChannel(executor);
+ public LinkedBlockingQueueChannel(ThreadPoolExecutor theExecutor) {
+ super(theExecutor);
}
- @Override
- public boolean subscribe(MessageHandler handler) {
- return mySubscribableChannel.subscribe(handler);
- }
-
- @Override
- public boolean unsubscribe(MessageHandler handler) {
- return mySubscribableChannel.unsubscribe(handler);
- }
-
- @Override
- public boolean send(Message> message, long timeout) {
- return mySubscribableChannel.send(message, timeout);
- }
-
- @VisibleForTesting
- public void clearInterceptorsForUnitTest() {
- mySubscribableChannel.setInterceptors(new ArrayList<>());
- }
-
- @VisibleForTesting
- public void addInterceptorForUnitTest(ChannelInterceptor theInterceptor) {
- mySubscribableChannel.addInterceptor(theInterceptor);
- }
-
- @VisibleForTesting
- public int getQueueSizeForUnitTest() {
- return myQueue.size();
- }
}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/LinkedBlockingQueueChannelFactory.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/LinkedBlockingQueueChannelFactory.java
index 07c2f0f710a..2f069fe6c9d 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/LinkedBlockingQueueChannelFactory.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/LinkedBlockingQueueChannelFactory.java
@@ -21,17 +21,27 @@ package ca.uhn.fhir.jpa.subscription.channel.queue;
*/
import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionConstants;
-import org.springframework.messaging.MessageChannel;
+import ca.uhn.fhir.util.StopWatch;
+import org.apache.commons.lang3.concurrent.BasicThreadFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.messaging.SubscribableChannel;
+import org.springframework.messaging.support.ExecutorSubscribableChannel;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.RejectedExecutionHandler;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
public class LinkedBlockingQueueChannelFactory implements IQueueChannelFactory {
- private Map myChannels = Collections.synchronizedMap(new HashMap<>());
+ private Map myChannels = Collections.synchronizedMap(new HashMap<>());
+ private static final Logger ourLog = LoggerFactory.getLogger(LinkedBlockingQueueChannelFactory.class);
/**
* Constructor
@@ -41,20 +51,49 @@ public class LinkedBlockingQueueChannelFactory implements IQueueChannelFactory {
}
@Override
- public SubscribableChannel getOrCreateReceiver(String theChannelName, Class> theMessageType, int theConcurrentConsumers) {
- return getOrCreateChannel(theChannelName, theConcurrentConsumers);
+ public IQueueChannelReceiver getOrCreateReceiver(String theChannelName, Class> theMessageType, QueueChannelConsumerConfig theConfig) {
+ return getOrCreateChannel(theChannelName, theConfig.getConcurrentConsumers());
}
@Override
- public MessageChannel getOrCreateSender(String theChannelName, Class> theMessageType, int theConcurrentConsumers) {
- return getOrCreateChannel(theChannelName, theConcurrentConsumers);
+ public IQueueChannelSender getOrCreateSender(String theChannelName, Class> theMessageType, QueueChannelConsumerConfig theConfig) {
+ return getOrCreateChannel(theChannelName, theConfig.getConcurrentConsumers());
}
- private SubscribableChannel getOrCreateChannel(String theChannelName, int theConcurrentConsumers) {
+ private LinkedBlockingQueueChannel getOrCreateChannel(String theChannelName, int theConcurrentConsumers) {
return myChannels.computeIfAbsent(theChannelName, t -> {
- LinkedBlockingQueue queue = new LinkedBlockingQueue<>(SubscriptionConstants.DELIVERY_EXECUTOR_QUEUE_SIZE);
+
String threadNamingPattern = theChannelName + "-%d";
- return new LinkedBlockingQueueChannel(queue, threadNamingPattern, theConcurrentConsumers);
+
+ ThreadFactory threadFactory = new BasicThreadFactory.Builder()
+ .namingPattern(threadNamingPattern)
+ .daemon(false)
+ .priority(Thread.NORM_PRIORITY)
+ .build();
+
+ LinkedBlockingQueue queue = new LinkedBlockingQueue<>(SubscriptionConstants.DELIVERY_EXECUTOR_QUEUE_SIZE);
+ RejectedExecutionHandler rejectedExecutionHandler = (theRunnable, theExecutor) -> {
+ ourLog.info("Note: Executor queue is full ({} elements), waiting for a slot to become available!", queue.size());
+ StopWatch sw = new StopWatch();
+ try {
+ queue.put(theRunnable);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new RejectedExecutionException("Task " + theRunnable.toString() +
+ " rejected from " + e.toString());
+ }
+ ourLog.info("Slot become available after {}ms", sw.getMillis());
+ };
+ ThreadPoolExecutor executor = new ThreadPoolExecutor(
+ 1,
+ theConcurrentConsumers,
+ 0L,
+ TimeUnit.MILLISECONDS,
+ queue,
+ threadFactory,
+ rejectedExecutionHandler);
+ return new LinkedBlockingQueueChannel(executor);
+
});
}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/QueueChannelConsumerConfig.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/QueueChannelConsumerConfig.java
new file mode 100644
index 00000000000..ce465b0ade7
--- /dev/null
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/queue/QueueChannelConsumerConfig.java
@@ -0,0 +1,35 @@
+package ca.uhn.fhir.jpa.subscription.channel.queue;
+
+/*-
+ * #%L
+ * HAPI FHIR Subscription Server
+ * %%
+ * Copyright (C) 2014 - 2020 University Health Network
+ * %%
+ * 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%
+ */
+
+public class QueueChannelConsumerConfig {
+
+ private int myConcurrentConsumers;
+
+ public int getConcurrentConsumers() {
+ return myConcurrentConsumers;
+ }
+
+ public void setConcurrentConsumers(int theConcurrentConsumers) {
+ myConcurrentConsumers = theConcurrentConsumers;
+ }
+
+}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelFactory.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelFactory.java
index 3603fbd8f23..c25aab6bfa0 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelFactory.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelFactory.java
@@ -21,23 +21,22 @@ package ca.uhn.fhir.jpa.subscription.channel.subscription;
*/
import ca.uhn.fhir.jpa.subscription.channel.queue.IQueueChannelFactory;
+import ca.uhn.fhir.jpa.subscription.channel.queue.IQueueChannelReceiver;
+import ca.uhn.fhir.jpa.subscription.channel.queue.IQueueChannelSender;
+import ca.uhn.fhir.jpa.subscription.channel.queue.QueueChannelConsumerConfig;
import ca.uhn.fhir.jpa.subscription.model.ResourceDeliveryJsonMessage;
import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedJsonMessage;
import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionConstants;
import org.apache.commons.lang3.Validate;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.messaging.Message;
-import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
-import org.springframework.messaging.MessagingException;
import org.springframework.messaging.SubscribableChannel;
import org.springframework.messaging.support.AbstractSubscribableChannel;
+import org.springframework.messaging.support.ChannelInterceptor;
public class SubscriptionChannelFactory {
- private static final Logger ourLog = LoggerFactory.getLogger(SubscriptionChannelFactory.class);
private final IQueueChannelFactory myQueueChannelFactory;
/**
@@ -48,24 +47,40 @@ public class SubscriptionChannelFactory {
myQueueChannelFactory = theQueueChannelFactory;
}
- public MessageChannel newDeliverySendingChannel(String theChannelName) {
- return myQueueChannelFactory.getOrCreateSender(theChannelName, ResourceDeliveryJsonMessage.class, getDeliveryChannelConcurrentConsumers());
+ public IQueueChannelSender newDeliverySendingChannel(String theChannelName) {
+ QueueChannelConsumerConfig config = newConfigForDeliveryChannel();
+ return myQueueChannelFactory.getOrCreateSender(theChannelName, ResourceDeliveryJsonMessage.class, config);
}
- public SubscribableChannel newDeliveryChannel(String theChannelName) {
- SubscribableChannel channel = myQueueChannelFactory.getOrCreateReceiver(theChannelName, ResourceDeliveryJsonMessage.class, getDeliveryChannelConcurrentConsumers());
+ public IQueueChannelReceiver newDeliveryReceivingChannel(String theChannelName) {
+ QueueChannelConsumerConfig config = newConfigForDeliveryChannel();
+ IQueueChannelReceiver channel = myQueueChannelFactory.getOrCreateReceiver(theChannelName, ResourceDeliveryJsonMessage.class, config);
return new BroadcastingSubscribableChannelWrapper(channel);
}
- public MessageChannel newMatchingSendingChannel(String theChannelName) {
- return myQueueChannelFactory.getOrCreateSender(theChannelName, ResourceModifiedJsonMessage.class, getMatchingChannelConcurrentConsumers());
+ public IQueueChannelSender newMatchingSendingChannel(String theChannelName) {
+ QueueChannelConsumerConfig config = newConfigForMatchingChannel();
+ return myQueueChannelFactory.getOrCreateSender(theChannelName, ResourceModifiedJsonMessage.class, config);
}
- public SubscribableChannel newMatchingReceivingChannel(String theChannelName) {
- SubscribableChannel channel = myQueueChannelFactory.getOrCreateReceiver(theChannelName, ResourceModifiedJsonMessage.class, getMatchingChannelConcurrentConsumers());
+ public IQueueChannelReceiver newMatchingReceivingChannel(String theChannelName) {
+ QueueChannelConsumerConfig config = newConfigForMatchingChannel();
+ IQueueChannelReceiver channel = myQueueChannelFactory.getOrCreateReceiver(theChannelName, ResourceModifiedJsonMessage.class, config);
return new BroadcastingSubscribableChannelWrapper(channel);
}
+ protected QueueChannelConsumerConfig newConfigForDeliveryChannel() {
+ QueueChannelConsumerConfig config = new QueueChannelConsumerConfig();
+ config.setConcurrentConsumers(getDeliveryChannelConcurrentConsumers());
+ return config;
+ }
+
+ protected QueueChannelConsumerConfig newConfigForMatchingChannel() {
+ QueueChannelConsumerConfig config = new QueueChannelConsumerConfig();
+ config.setConcurrentConsumers(getMatchingChannelConcurrentConsumers());
+ return config;
+ }
+
public int getDeliveryChannelConcurrentConsumers() {
return SubscriptionConstants.DELIVERY_CHANNEL_CONCURRENT_CONSUMERS;
}
@@ -74,12 +89,12 @@ public class SubscriptionChannelFactory {
return SubscriptionConstants.MATCHING_CHANNEL_CONCURRENT_CONSUMERS;
}
- public static class BroadcastingSubscribableChannelWrapper extends AbstractSubscribableChannel implements MessageHandler, DisposableBean {
+ public static class BroadcastingSubscribableChannelWrapper extends AbstractSubscribableChannel implements IQueueChannelReceiver, DisposableBean {
- private final SubscribableChannel myWrappedChannel;
+ private final IQueueChannelReceiver myWrappedChannel;
- public BroadcastingSubscribableChannelWrapper(SubscribableChannel theChannel) {
- theChannel.subscribe(this);
+ public BroadcastingSubscribableChannelWrapper(IQueueChannelReceiver theChannel) {
+ theChannel.subscribe(message -> send(message));
myWrappedChannel = theChannel;
}
@@ -89,20 +104,10 @@ public class SubscriptionChannelFactory {
@Override
protected boolean sendInternal(Message> theMessage, long timeout) {
-// try {
- for (MessageHandler next : getSubscribers()) {
- next.handleMessage(theMessage);
- }
- return true;
-// } catch (Exception e) {
-// ourLog.error("Failiure handling message", e);
-// return false;
-// }
- }
-
- @Override
- public void handleMessage(Message> message) throws MessagingException {
- send(message);
+ for (MessageHandler next : getSubscribers()) {
+ next.handleMessage(theMessage);
+ }
+ return true;
}
@Override
@@ -112,5 +117,12 @@ public class SubscriptionChannelFactory {
}
}
+ @Override
+ public void addInterceptor(ChannelInterceptor interceptor) {
+ super.addInterceptor(interceptor);
+ myWrappedChannel.addInterceptor(interceptor);
+ }
+
+
}
}
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelRegistry.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelRegistry.java
index d5bffd1cb5c..f38def3d0f9 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelRegistry.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelRegistry.java
@@ -22,7 +22,6 @@ package ca.uhn.fhir.jpa.subscription.channel.subscription;
import ca.uhn.fhir.jpa.subscription.process.registry.ActiveSubscription;
import ca.uhn.fhir.jpa.subscription.process.registry.SubscriptionRegistry;
-import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Multimap;
import com.google.common.collect.MultimapBuilder;
import org.slf4j.Logger;
@@ -32,7 +31,6 @@ import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.SubscribableChannel;
-import java.util.Collection;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
@@ -61,7 +59,7 @@ public class SubscriptionChannelRegistry {
return;
}
- SubscribableChannel deliveryChannel = mySubscriptionDeliveryChannelFactory.newDeliveryChannel(channelName);
+ SubscribableChannel deliveryChannel = mySubscriptionDeliveryChannelFactory.newDeliveryReceivingChannel(channelName);
Optional deliveryHandler = mySubscriptionDeliveryHandlerFactory.createDeliveryHandler(theActiveSubscription.getChannelType());
SubscriptionChannelWithHandlers subscriptionChannelWithHandlers = new SubscriptionChannelWithHandlers(channelName, deliveryChannel);
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/config/SubscriptionProcessorConfig.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/config/SubscriptionProcessorConfig.java
index 1f7eed79122..318ab1c403a 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/config/SubscriptionProcessorConfig.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/config/SubscriptionProcessorConfig.java
@@ -97,11 +97,6 @@ public class SubscriptionProcessorConfig {
return new DaoResourceRetriever();
}
- @Bean
- public WebsocketConnectionValidator websocketConnectionValidator() {
- return new WebsocketConnectionValidator();
- }
-
@Bean
public SubscriptionLoader subscriptionLoader() {
return new SubscriptionLoader();
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/WebsocketDispatcherConfig.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/config/WebsocketDispatcherConfig.java
similarity index 87%
rename from hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/WebsocketDispatcherConfig.java
rename to hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/config/WebsocketDispatcherConfig.java
index c88275d7cb6..845c52322b9 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/WebsocketDispatcherConfig.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/config/WebsocketDispatcherConfig.java
@@ -1,8 +1,8 @@
-package ca.uhn.fhir.jpa.config;
+package ca.uhn.fhir.jpa.subscription.process.config;
/*
* #%L
- * HAPI FHIR JPA Server
+ * HAPI FHIR Subscription Server
* %%
* Copyright (C) 2014 - 2020 University Health Network
* %%
@@ -22,6 +22,7 @@ package ca.uhn.fhir.jpa.config;
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
import ca.uhn.fhir.jpa.subscription.process.deliver.websocket.SubscriptionWebsocketHandler;
+import ca.uhn.fhir.jpa.subscription.process.deliver.websocket.WebsocketConnectionValidator;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
@@ -37,9 +38,15 @@ import org.springframework.web.socket.handler.PerConnectionWebSocketHandler;
@EnableWebSocket()
@Controller
public class WebsocketDispatcherConfig implements WebSocketConfigurer {
+
@Autowired
ModelConfig myModelConfig;
+ @Bean
+ public WebsocketConnectionValidator websocketConnectionValidator() {
+ return new WebsocketConnectionValidator();
+ }
+
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry theRegistry) {
theRegistry.addHandler(subscriptionWebSocketHandler(), myModelConfig.getWebsocketContextPath()).setAllowedOrigins("*");
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/websocket/SubscriptionWebsocketHandler.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/websocket/SubscriptionWebsocketHandler.java
index 58d0ebe8a3b..c36e686de85 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/websocket/SubscriptionWebsocketHandler.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/websocket/SubscriptionWebsocketHandler.java
@@ -50,6 +50,13 @@ public class SubscriptionWebsocketHandler extends TextWebSocketHandler implement
@Autowired
SubscriptionChannelRegistry mySubscriptionChannelRegistry;
+ /**
+ * Constructor
+ */
+ public SubscriptionWebsocketHandler() {
+ super();
+ }
+
@Autowired
private FhirContext myCtx;
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/websocket/WebsocketConnectionValidator.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/websocket/WebsocketConnectionValidator.java
index 0442db66a03..73819f05db2 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/websocket/WebsocketConnectionValidator.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/deliver/websocket/WebsocketConnectionValidator.java
@@ -36,6 +36,13 @@ public class WebsocketConnectionValidator {
SubscriptionRegistry mySubscriptionRegistry;
+ /**
+ * Constructor
+ */
+ public WebsocketConnectionValidator() {
+ super();
+ }
+
public WebsocketValidationResponse validate(@NotNull IdType id) {
if (!id.hasIdPart() || !id.isIdPartValid()) {
return WebsocketValidationResponse.INVALID_RESPONSE("Invalid bind request - No ID included: " + id.getValue());
diff --git a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/BaseSubscriberForSubscriptionResources.java b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/BaseSubscriberForSubscriptionResources.java
index 730296ab0f8..d81a86a8212 100644
--- a/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/BaseSubscriberForSubscriptionResources.java
+++ b/hapi-fhir-jpaserver-subscription/src/main/java/ca/uhn/fhir/jpa/subscription/process/matcher/subscriber/BaseSubscriberForSubscriptionResources.java
@@ -36,9 +36,19 @@ public abstract class BaseSubscriberForSubscriptionResources implements MessageH
protected FhirContext myFhirContext;
protected boolean isSubscription(ResourceModifiedMessage theNewResource) {
- IBaseResource payload = theNewResource.getNewPayload(myFhirContext);
- String payloadIdType = myFhirContext.getResourceDefinition(payload).getName();
- return payloadIdType.equals(ResourceTypeEnum.SUBSCRIPTION.getCode());
+ String payloadIdType = null;
+ IIdType payloadId = theNewResource.getId(myFhirContext);
+ if (payloadId != null) {
+ payloadIdType = payloadId.getResourceType();
+ }
+ if (isBlank(payloadIdType)) {
+ IBaseResource payload = theNewResource.getNewPayload(myFhirContext);
+ if (payload != null) {
+ payloadIdType = myFhirContext.getResourceDefinition(payload).getName();
+ }
+ }
+
+ return ResourceTypeEnum.SUBSCRIPTION.getCode().equals(payloadIdType);
}
}
diff --git a/hapi-fhir-jpaserver-subscription/src/test/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelFactoryTest.java b/hapi-fhir-jpaserver-subscription/src/test/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelFactoryTest.java
new file mode 100644
index 00000000000..6f3b979551d
--- /dev/null
+++ b/hapi-fhir-jpaserver-subscription/src/test/java/ca/uhn/fhir/jpa/subscription/channel/subscription/SubscriptionChannelFactoryTest.java
@@ -0,0 +1,76 @@
+package ca.uhn.fhir.jpa.subscription.channel.subscription;
+
+import ca.uhn.fhir.jpa.subscription.channel.queue.IQueueChannelReceiver;
+import ca.uhn.fhir.jpa.subscription.channel.queue.LinkedBlockingQueueChannelFactory;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.springframework.messaging.Message;
+import org.springframework.messaging.MessageDeliveryException;
+import org.springframework.messaging.MessageHandler;
+import org.springframework.messaging.MessagingException;
+import org.springframework.messaging.support.ChannelInterceptor;
+import org.springframework.messaging.support.GenericMessage;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class SubscriptionChannelFactoryTest {
+
+ private SubscriptionChannelFactory mySvc;
+
+ @Mock
+ private ChannelInterceptor myInterceptor;
+ @Captor
+ private ArgumentCaptor myExceptionCaptor;
+
+ @Before
+ public void before() {
+ mySvc = new SubscriptionChannelFactory(new LinkedBlockingQueueChannelFactory());
+ }
+
+ /**
+ * Make sure the channel doesn't silently swallow exceptions
+ */
+ @Test
+ public void testInterceptorsOnChannelWrapperArePropagated() {
+
+ IQueueChannelReceiver channel = mySvc.newDeliveryReceivingChannel("CHANNEL_NAME");
+ channel.subscribe(new NpeThrowingHandler());
+ channel.addInterceptor(myInterceptor);
+
+ Message> input = new GenericMessage<>("TEST");
+
+ when(myInterceptor.preSend(any(),any())).thenAnswer(t->t.getArgument(0, Message.class));
+ when(myInterceptor.postReceive(any(),any())).thenAnswer(t->t.getArgument(0, Message.class));
+
+ try {
+ channel.send(input);
+ fail();
+ } catch (MessageDeliveryException e) {
+ assertTrue(e.getCause() instanceof NullPointerException);
+ }
+
+ verify(myInterceptor, times(1)).afterSendCompletion(any(), any(), anyBoolean(), myExceptionCaptor.capture());
+
+ assertTrue(myExceptionCaptor.getValue() instanceof NullPointerException);
+ }
+
+
+ private class NpeThrowingHandler implements MessageHandler {
+ @Override
+ public void handleMessage(Message> message) throws MessagingException {
+ throw new NullPointerException("THIS IS THE MESSAGE");
+ }
+ }
+}
diff --git a/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/TestRestfulServer.java b/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/TestRestfulServer.java
index 52d8ffaa687..c1bdde59ea3 100644
--- a/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/TestRestfulServer.java
+++ b/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/TestRestfulServer.java
@@ -6,7 +6,7 @@ import ca.uhn.fhir.jpa.api.config.DaoConfig;
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
import ca.uhn.fhir.jpa.api.dao.IFhirSystemDao;
import ca.uhn.fhir.jpa.bulk.BulkDataExportProvider;
-import ca.uhn.fhir.jpa.config.WebsocketDispatcherConfig;
+import ca.uhn.fhir.jpa.subscription.process.config.WebsocketDispatcherConfig;
import ca.uhn.fhir.jpa.interceptor.CascadingDeleteInterceptor;
import ca.uhn.fhir.jpa.provider.GraphQLProvider;
import ca.uhn.fhir.jpa.provider.JpaConformanceProviderDstu2;
@@ -20,7 +20,6 @@ import ca.uhn.fhir.jpa.provider.r5.JpaConformanceProviderR5;
import ca.uhn.fhir.jpa.provider.r5.JpaSystemProviderR5;
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
-import ca.uhn.fhir.jpa.subscription.submit.interceptor.SubscriptionSubmitInterceptorLoader;
import ca.uhn.fhir.jpa.util.ResourceProviderFactory;
import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
import ca.uhn.fhir.rest.api.EncodingEnum;
diff --git a/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/config/CommonConfig.java b/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/config/CommonConfig.java
index 53bb186f8c2..9a964fd103b 100644
--- a/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/config/CommonConfig.java
+++ b/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/config/CommonConfig.java
@@ -1,6 +1,6 @@
package ca.uhn.fhirtest.config;
-import ca.uhn.fhir.jpa.config.WebsocketDispatcherConfig;
+import ca.uhn.fhir.jpa.subscription.process.config.WebsocketDispatcherConfig;
import ca.uhn.fhir.jpa.subscription.channel.config.SubscriptionChannelConfig;
import ca.uhn.fhir.jpa.subscription.process.config.SubscriptionProcessorConfig;
import ca.uhn.fhir.jpa.subscription.submit.config.SubscriptionSubmitterConfig;
diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/SearchNarrowingInterceptor.java_703256810379985 b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/SearchNarrowingInterceptor.java_703256810379985
new file mode 100644
index 00000000000..3ede68f6b6a
--- /dev/null
+++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/SearchNarrowingInterceptor.java_703256810379985
@@ -0,0 +1,278 @@
+package ca.uhn.fhir.rest.server.interceptor.auth;
+
+/*-
+ * #%L
+ * HAPI FHIR - Server Framework
+ * %%
+ * Copyright (C) 2014 - 2020 University Health Network
+ * %%
+ * 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%
+ */
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.context.RuntimeResourceDefinition;
+import ca.uhn.fhir.context.RuntimeSearchParam;
+import ca.uhn.fhir.interceptor.api.Hook;
+import ca.uhn.fhir.interceptor.api.Pointcut;
+import ca.uhn.fhir.rest.api.QualifiedParamList;
+import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
+import ca.uhn.fhir.rest.api.server.RequestDetails;
+import ca.uhn.fhir.rest.param.ParameterUtil;
+import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
+import ca.uhn.fhir.rest.server.method.BaseMethodBinding;
+import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
+import ca.uhn.fhir.rest.server.servlet.ServletSubRequestDetails;
+import ca.uhn.fhir.rest.server.util.ServletRequestUtil;
+import ca.uhn.fhir.util.BundleUtil;
+import ca.uhn.fhir.util.bundle.ModifiableBundleEntry;
+import com.google.common.collect.ArrayListMultimap;
+import org.apache.commons.collections4.ListUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.Validate;
+import org.hl7.fhir.instance.model.api.IBaseBundle;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.*;
+import java.util.function.Consumer;
+
+/**
+ * This interceptor can be used to automatically narrow the scope of searches in order to
+ * automatically restrict the searches to specific compartments.
+ *
+ * For example, this interceptor
+ * could be used to restrict a user to only viewing data belonging to Patient/123 (i.e. data
+ * in the Patient/123 compartment). In this case, a user performing a search
+ * for
+ * http://baseurl/Observation?category=laboratory
+ * would receive results as though they had requested
+ * http://baseurl/Observation?subject=Patient/123&category=laboratory
+ *
+ *
+ * Note that this interceptor should be used in combination with {@link AuthorizationInterceptor}
+ * if you are restricting results because of a security restriction. This interceptor is not
+ * intended to be a failsafe way of preventing users from seeing the wrong data (that is the
+ * purpose of AuthorizationInterceptor). This interceptor is simply intended as a convenience to
+ * help users simplify their queries while not receiving security errors for to trying to access
+ * data they do not have access to see.
+ *
+ *
+ * @see AuthorizationInterceptor
+ */
+public class SearchNarrowingInterceptor {
+ private static final Logger ourLog = LoggerFactory.getLogger(SearchNarrowingInterceptor.class);
+
+
+ /**
+ * Subclasses should override this method to supply the set of compartments that
+ * the user making the request should actually have access to.
+ *
+ * Typically this is done by examining theRequestDetails to find
+ * out who the current user is and then building a list of Strings.
+ *
- * Implementations can choose to return the same object for multiple invocations of this method (and {@link #getOrCreateReceiver(String, Class, QueueChannelConsumerConfig)}
+ * Implementations can choose to return the same object for multiple invocations of this method (and {@link #getOrCreateReceiver(String, Class, ChannelConsumerOptions)}
* when invoked with the same {@literal theChannelName} if they need to, or they can create a new instance.
*
*
@@ -38,18 +38,18 @@ public interface IQueueChannelFactory {
* @param theMessageType The object type that will be placed on this queue. Objects will be Jackson-annotated structures.
* @param theConfig Contains the configuration for subscribers. Note that this parameter is provided for
* both {@link #getOrCreateReceiver} and
- * {@link #getOrCreateSender(String, Class, QueueChannelConsumerConfig)}
+ * {@link #getOrCreateSender(String, Class, ChannelConsumerOptions)}
* even though this object is used to configure the sender only. We do this because the factory
* may want to create a single object to be used for both the sender and receiver, so this allows
* the config details to be known regardless of which method is returned first.
*/
- IQueueChannelReceiver getOrCreateReceiver(String theChannelName, Class> theMessageType, QueueChannelConsumerConfig theConfig);
+ IChannelReceiver getOrCreateReceiver(String theChannelName, Class> theMessageType, ChannelConsumerOptions theConfig);
/**
* Create a channel that is used to send messages to the queue.
*
*
- * Implementations can choose to return the same object for multiple invocations of this method (and {@link #getOrCreateReceiver(String, Class, QueueChannelConsumerConfig)}
+ * Implementations can choose to return the same object for multiple invocations of this method (and {@link #getOrCreateReceiver(String, Class, ChannelConsumerOptions)}
* when invoked with the same {@literal theChannelName} if they need to, or they can create a new instance.
*