diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index e65c30f59b..5f7cd1b567 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,19 @@ # Release Notes +## Version 47.7.0 +_6 January 2025_ + +### Features +* Add endpoints to retrieve data for the Developer Attestation PowerBI report +* Allow changing of ATL using upload-to-update +* Save activity for created and deleted invitations +* Add job to update Service Base URL report items + +### Bug Fixes +* Give ONC users ability to edit listing via upload + +--- + ## Version 47.6.0 _18 December 2024_ diff --git a/chpl/chpl-api/e2e/collections/activity-controller.postman_collection.json b/chpl/chpl-api/e2e/collections/activity-controller.postman_collection.json index 74e852613c..ffa5098f09 100644 --- a/chpl/chpl-api/e2e/collections/activity-controller.postman_collection.json +++ b/chpl/chpl-api/e2e/collections/activity-controller.postman_collection.json @@ -233,15 +233,16 @@ "name": "ROLE_ACB", "item": [ { - "name": "GET /activity/metadata/svaps - ACB user gets 401 status and no response", + "name": "GET /activity/metadata/svaps - ACB user gets 200 status and valid response", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test(\"ACB user gets 401 status and valid response from /activity/metadata/svaps end point\", function () {\r", + "pm.test(\"ACB user gets 200 status and valid response from /activity/metadata/svaps end point\", function () {\r", " var actualResponseBody = pm.response.json();\r", - " pm.response.to.have.status(401);\r", + " pm.response.to.have.status(200);\r", + " pm.expect(actualResponseBody).not.eql(null);\r", "});" ], "type": "text/javascript", @@ -285,20 +286,21 @@ "svaps" ] }, - "description": "GET /activity/metadata/svaps - ACB user gets 401 status and no response" + "description": "GET /activity/metadata/svaps - ACB user gets 200 status and valid response" }, "response": [] }, { - "name": "GET /activity/metadata/standards - ACB user gets 401 status and no response", + "name": "GET /activity/metadata/standards - ACB user gets 200 status and valid response", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test(\"ACB user gets 401 status and valid response from /activity/metadata/standards end point\", function () {\r", + "pm.test(\"ACB user gets 200 status and valid response from /activity/metadata/standards end point\", function () {\r", " var actualResponseBody = pm.response.json();\r", - " pm.response.to.have.status(401);\r", + " pm.response.to.have.status(200);\r", + " pm.expect(actualResponseBody).not.eql(null);\r", "});" ], "type": "text/javascript", @@ -342,20 +344,21 @@ "standards" ] }, - "description": "GET /activity/metadata/standards - ACB user gets 401 status and no response" + "description": "GET /activity/metadata/standards - ACB user gets 200 status and valid response" }, "response": [] }, { - "name": "GET /activity/metadata/functionalities-tested - ACB user gets 401 status and no response", + "name": "GET /activity/metadata/functionalities-tested - ACB user gets 200 status and valid response", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test(\"ACB user gets 401 status and valid response from /activity/metadata/functionalities-tested end point\", function () {\r", + "pm.test(\"ACB user gets 200 status and valid response from /activity/metadata/functionalities-tested end point\", function () {\r", " var actualResponseBody = pm.response.json();\r", - " pm.response.to.have.status(401);\r", + " pm.response.to.have.status(200);\r", + " pm.expect(actualResponseBody).not.eql(null);\r", "});" ], "type": "text/javascript", @@ -399,7 +402,7 @@ "functionalities-tested" ] }, - "description": "GET /activity/metadata/functionalities-tested - ACB user gets 401 status and no response" + "description": "GET /activity/metadata/functionalities-tested - ACB user gets 200 status and valid response" }, "response": [] } diff --git a/chpl/chpl-api/e2e/collections/test-tools-controller.postman_collection.json b/chpl/chpl-api/e2e/collections/test-tools-controller.postman_collection.json index 22711c9341..deecb35652 100644 --- a/chpl/chpl-api/e2e/collections/test-tools-controller.postman_collection.json +++ b/chpl/chpl-api/e2e/collections/test-tools-controller.postman_collection.json @@ -225,7 +225,7 @@ "name": "ROLE_ONC", "item": [ { - "name": "POST /test-tools - ROLE_ONC user should get 401 status and access denied error", + "name": "POST /test-tools - ROLE_ONC user should get 200 status", "event": [ { "listen": "prerequest", @@ -240,8 +240,8 @@ "listen": "test", "script": { "exec": [ - "pm.test(\"create test tools request by ROLE_ONC user should return Status code 401\", function () {\r", - " pm.response.to.have.status(401);\r", + "pm.test(\"create test tools request by ROLE_ONC user should return Status code 200\", function () {\r", + " pm.response.to.have.status(200);\r", "});\r" ], "type": "text/javascript" @@ -274,7 +274,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"id\":1,\r\n \"value\": \"test\",\r\n \"regulatoryTextCitation\": \"test1\",\r\n \"startDay\": \"2023-07-12\",\r\n \"endDay\": \"2023-07-12\",\r\n \"requiredDay\": \"2023-07-12\",\r\n \"criteria\": [\r\n {\r\n \"id\": 0,\r\n \"number\": \"string\",\r\n \"title\": \"string\",\r\n \"certificationEditionId\": 0,\r\n \"certificationEdition\": \"string\",\r\n \"description\": \"string\",\r\n \"removed\": true\r\n }\r\n ],\r\n \"rule\": {\r\n \"id\": 0,\r\n \"name\": \"string\"\r\n }\r\n}" + "raw": "{\r\n \"value\": \"new tt\",\r\n \"regulatoryTextCitation\": \"newtt\",\r\n \"startDay\": \"2025-01-01\",\r\n \"endDay\": \"\",\r\n \"criteria\": [\r\n {\r\n \"id\": 165,\r\n \"number\": \"170.315 (b)(1)\",\r\n \"title\": \"Transitions of Care\",\r\n \"certificationEditionId\": 3,\r\n \"certificationEdition\": \"2015\",\r\n \"description\": null,\r\n \"removed\": false\r\n }\r\n ],\r\n \"rule\": {\r\n \"id\": 5,\r\n \"name\": \"HTI-1\"\r\n }\r\n}" }, "url": { "raw": "{{url}}/rest/test-tools", @@ -286,19 +286,19 @@ "test-tools" ] }, - "description": "ROLE_ONC user should get 401 status and access denied error to create Test Tools" + "description": "ROLE_ONC user should get 200 status to create Test Tools" }, "response": [] }, { - "name": "PUT /test-tools - ROLE_ONC user should get 401 status and access denied error", + "name": "PUT /test-tools - ROLE_ONC user should get 200 status", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test(\"edit test tools request by ROLE_ONC user should return Status code 401\", function () {\r", - " pm.response.to.have.status(401);\r", + "pm.test(\"edit test tools request by ROLE_ONC user should return Status code 200\", function () {\r", + " pm.response.to.have.status(200);\r", "});\r" ], "type": "text/javascript" @@ -331,7 +331,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"id\": 1,\r\n \"value\": \"test2\",\r\n \"regulatoryTextCitation\": \"test3\",\r\n \"startDay\": \"2023-07-13\",\r\n \"endDay\": \"2023-07-13\",\r\n \"requiredDay\": \"2023-07-13\",\r\n \"criteria\": [\r\n {\r\n \"id\": 0,\r\n \"number\": \"string\",\r\n \"title\": \"string\",\r\n \"certificationEditionId\": 0,\r\n \"certificationEdition\": \"string\",\r\n \"description\": \"string\",\r\n \"removed\": true\r\n }\r\n ],\r\n \"rule\": {\r\n \"id\": 0,\r\n \"name\": \"string\"\r\n }\r\n}" + "raw": "{\r\n \"id\":33,\r\n \"value\": \"Drummond G10+ FHIR API powered by Touchstone\",\r\n \"regulatoryTextCitation\": \"Touchstone\",\r\n \"startDay\": \"\",\r\n \"endDay\": \"\",\r\n \"criteria\": [\r\n {\r\n \"id\": 182,\r\n \"number\": \"170.315 (g)(10)\",\r\n \"title\": \"Standardized API for Patient and Population Services\",\r\n \"certificationEditionId\": 3,\r\n \"certificationEdition\": \"2015\",\r\n \"description\": null,\r\n \"removed\": false,\r\n \"rule\": {\r\n \"id\": 4,\r\n \"name\": \"Cures\"\r\n },\r\n \"startDay\": \"2020-06-30\",\r\n \"endDay\": null\r\n }\r\n ],\r\n \"rule\": {\r\n \"id\": 5,\r\n \"name\": \"HTI-1\"\r\n }\r\n}" }, "url": { "raw": "{{url}}/rest/test-tools", @@ -343,7 +343,7 @@ "test-tools" ] }, - "description": "PUT /test-tools - ROLE_ONC user should get 401 status and access denied error" + "description": "PUT /test-tools - ROLE_ONC user should get 200 status" }, "response": [] }, diff --git a/chpl/chpl-api/src/main/java/gov/healthit/chpl/web/controller/ActivityController.java b/chpl/chpl-api/src/main/java/gov/healthit/chpl/web/controller/ActivityController.java index 2de2d21e8e..988190abfb 100644 --- a/chpl/chpl-api/src/main/java/gov/healthit/chpl/web/controller/ActivityController.java +++ b/chpl/chpl-api/src/main/java/gov/healthit/chpl/web/controller/ActivityController.java @@ -339,7 +339,6 @@ public List metadataForProductById(@PathVariable("id") final L }) @RequestMapping(value = "/metadata/versions", method = RequestMethod.GET, produces = "application/json; charset=utf-8") - @DeprecatedApiResponseFields(friendlyUrl = "/activity/metadata/versions", responseClass = ActivityMetadataPage.class) public ActivityMetadataPage metadataForVersions(@RequestParam(required = false) Long start, @RequestParam(required = false) Long end, @RequestParam(required = false) Integer pageNum, @RequestParam(required = false) Integer pageSize) throws JsonParseException, IOException, ValidationException { @@ -354,7 +353,6 @@ public ActivityMetadataPage metadataForVersions(@RequestParam(required = false) }) @RequestMapping(value = "/metadata/versions/{id:^-?\\d+$}", method = RequestMethod.GET, produces = "application/json; charset=utf-8") - @DeprecatedApiResponseFields(friendlyUrl = "/activity/metadata/versions/{id}", responseClass = ActivityMetadata.class) public List metadataForVersionById(@PathVariable("id") final Long id, @RequestParam(required = false) final Long start, @RequestParam(required = false) final Long end) throws JsonParseException, IOException, EntityRetrievalException, ValidationException { @@ -390,7 +388,6 @@ public List metadataForVersionById(@PathVariable("id") final L }) @RequestMapping(value = "/metadata/acbs", method = RequestMethod.GET, produces = "application/json; charset=utf-8") - @DeprecatedApiResponseFields(friendlyUrl = "/activity/metadata/acbs", responseClass = ActivityMetadataPage.class) public ActivityMetadataPage metadataForAcbs(@RequestParam(required = false) Long start, @RequestParam(required = false) Long end, @RequestParam(required = false) Integer pageNum, @RequestParam(required = false) Integer pageSize) throws JsonParseException, IOException, ValidationException { @@ -405,7 +402,6 @@ public ActivityMetadataPage metadataForAcbs(@RequestParam(required = false) Long }) @RequestMapping(value = "/metadata/acbs/{id:^-?\\d+$}", method = RequestMethod.GET, produces = "application/json; charset=utf-8") - @DeprecatedApiResponseFields(friendlyUrl = "/activity/metadata/acbs/{id}", responseClass = ActivityMetadata.class) public List metadataForAcbById(@PathVariable("id") final Long id, @RequestParam(required = false) final Long start, @RequestParam(required = false) final Long end) throws JsonParseException, IOException, EntityRetrievalException, ValidationException { @@ -438,7 +434,6 @@ public List metadataForAcbById(@PathVariable("id") final Long }) @RequestMapping(value = "/metadata/atls", method = RequestMethod.GET, produces = "application/json; charset=utf-8") - @DeprecatedApiResponseFields(friendlyUrl = "/activity/metadata/atls", responseClass = ActivityMetadataPage.class) public ActivityMetadataPage metadataForAtls(@RequestParam(required = false) Long start, @RequestParam(required = false) Long end, @RequestParam(required = false) Integer pageNum, @RequestParam(required = false) Integer pageSize) throws JsonParseException, IOException, ValidationException { @@ -453,7 +448,6 @@ public ActivityMetadataPage metadataForAtls(@RequestParam(required = false) Long }) @RequestMapping(value = "/metadata/atls/{id:^-?\\d+$}", method = RequestMethod.GET, produces = "application/json; charset=utf-8") - @DeprecatedApiResponseFields(friendlyUrl = "/activity/metadata/atls/{id}", responseClass = ActivityMetadata.class) public List metadataForAtlById(@PathVariable("id") final Long id, @RequestParam(required = false) final Long start, @RequestParam(required = false) final Long end) throws JsonParseException, IOException, EntityRetrievalException, ValidationException { @@ -485,7 +479,6 @@ public List metadataForAtlById(@PathVariable("id") final Long @SecurityRequirement(name = SwaggerSecurityRequirement.BEARER) }) @RequestMapping(value = "/metadata/users", method = RequestMethod.GET, produces = "application/json; charset=utf-8") - @DeprecatedApiResponseFields(friendlyUrl = "/activity/metadata/users", responseClass = ActivityMetadataPage.class) public ActivityMetadataPage metadataForUsers(@RequestParam(required = false) Long start, @RequestParam(required = false) Long end, @RequestParam(required = false) Integer pageNum, @RequestParam(required = false) Integer pageSize) throws JsonParseException, IOException, ValidationException { @@ -504,7 +497,6 @@ public ActivityMetadataPage metadataForUsers(@RequestParam(required = false) Lon }) @RequestMapping(value = "/metadata/announcements", method = RequestMethod.GET, produces = "application/json; charset=utf-8") - @DeprecatedApiResponseFields(friendlyUrl = "/activity/metadata/announcements", responseClass = ActivityMetadataPage.class) public ActivityMetadataPage metadataForAnnouncements(@RequestParam(required = false) Long start, @RequestParam(required = false) Long end, @RequestParam(required = false) Integer pageNum, @RequestParam(required = false) Integer pageSize) throws JsonParseException, IOException, ValidationException { @@ -520,7 +512,6 @@ public ActivityMetadataPage metadataForAnnouncements(@RequestParam(required = fa @SecurityRequirement(name = SwaggerSecurityRequirement.BEARER) }) @RequestMapping(value = "/metadata/complaints", method = RequestMethod.GET, produces = "application/json; charset=utf-8") - @DeprecatedApiResponseFields(friendlyUrl = "/activity/metadata/complaints", responseClass = ActivityMetadata.class) public List metadataForComplaints(@RequestParam final Long start, @RequestParam final Long end) throws JsonParseException, IOException, ValidationException { Date startDate = new Date(start); @@ -538,7 +529,6 @@ public List metadataForComplaints(@RequestParam final Long sta @SecurityRequirement(name = SwaggerSecurityRequirement.BEARER) }) @RequestMapping(value = "/metadata/quarterly-reports", method = RequestMethod.GET, produces = "application/json; charset=utf-8") - @DeprecatedApiResponseFields(friendlyUrl = "/activity/metadata/quarterly-reports", responseClass = ActivityMetadata.class) public List metadataForQuarterlyReports(@RequestParam final Long start, @RequestParam final Long end) throws JsonParseException, IOException, ValidationException { @@ -566,7 +556,6 @@ public List metadataForQuarterlyReports(@RequestParam final Lo @SecurityRequirement(name = SwaggerSecurityRequirement.BEARER) }) @RequestMapping(value = "/metadata/annual-reports", method = RequestMethod.GET, produces = "application/json; charset=utf-8") - @DeprecatedApiResponseFields(friendlyUrl = "/activity/metadata/annual-reports", responseClass = ActivityMetadata.class) public List metadataForAnnualReports(@RequestParam final Long start, @RequestParam final Long end) throws JsonParseException, IOException, ValidationException { Date startDate = new Date(start); @@ -583,7 +572,6 @@ public List metadataForAnnualReports(@RequestParam final Long @SecurityRequirement(name = SwaggerSecurityRequirement.API_KEY) }) @RequestMapping(value = "/metadata/corrective-action-plans", method = RequestMethod.GET, produces = "application/json; charset=utf-8") - @DeprecatedApiResponseFields(friendlyUrl = "/activity/metadata/corrective-action-plans", responseClass = ActivityMetadataPage.class) public ActivityMetadataPage metadataForCorrectiveActionPlans(@RequestParam(required = false) Long start, @RequestParam(required = false) Long end, @RequestParam(required = false) Integer pageNum, @RequestParam(required = false) Integer pageSize) throws JsonParseException, IOException, ValidationException { @@ -601,7 +589,6 @@ public ActivityMetadataPage metadataForCorrectiveActionPlans(@RequestParam(requi }) @RequestMapping(value = "/metadata/pending-surveillances", method = RequestMethod.GET, produces = "application/json; charset=utf-8") - @DeprecatedApiResponseFields(friendlyUrl = "/activity/metadata/pending-surveillances", responseClass = ActivityMetadataPage.class) public ActivityMetadataPage metadataForPendingSurveillances(@RequestParam(required = false) Long start, @RequestParam(required = false) Long end, @RequestParam(required = false) Integer pageNum, @RequestParam(required = false) Integer pageSize) throws JsonParseException, IOException, ValidationException { @@ -618,7 +605,6 @@ public ActivityMetadataPage metadataForPendingSurveillances(@RequestParam(requir }) @RequestMapping(value = "/metadata/change-requests", method = RequestMethod.GET, produces = "application/json; charset=utf-8") - @DeprecatedApiResponseFields(friendlyUrl = "/activity/metadata/change-requests", responseClass = ActivityMetadata.class) public List metadataForChangeRequests(@RequestParam final Long start, @RequestParam final Long end) throws JsonParseException, IOException, ValidationException { Date startDate = new Date(start); @@ -637,7 +623,6 @@ public List metadataForChangeRequests(@RequestParam final Long }) @RequestMapping(value = "/metadata/api-keys", method = RequestMethod.GET, produces = "application/json; charset=utf-8") - @DeprecatedApiResponseFields(friendlyUrl = "/activity/metadata/api-keys", responseClass = ActivityMetadataPage.class) public ActivityMetadataPage metadataForApiKeys(@RequestParam(required = false) Long start, @RequestParam(required = false) Long end, @RequestParam(required = false) Integer pageNum, @RequestParam(required = false) Integer pageSize) throws JsonParseException, IOException, ValidationException { @@ -654,7 +639,6 @@ public ActivityMetadataPage metadataForApiKeys(@RequestParam(required = false) L }) @RequestMapping(value = "/metadata/functionalities-tested", method = RequestMethod.GET, produces = "application/json; charset=utf-8") - @DeprecatedApiResponseFields(friendlyUrl = "/activity/metadata/functionalities-tested", responseClass = ActivityMetadataPage.class) public ActivityMetadataPage metadataForFunctionalitiesTested(@RequestParam(required = false) Long start, @RequestParam(required = false) Long end, @RequestParam(required = false) Integer pageNum, @RequestParam(required = false) Integer pageSize) throws JsonParseException, IOException, ValidationException { @@ -671,7 +655,6 @@ public ActivityMetadataPage metadataForFunctionalitiesTested(@RequestParam(requi }) @RequestMapping(value = "/metadata/standards", method = RequestMethod.GET, produces = "application/json; charset=utf-8") - @DeprecatedApiResponseFields(friendlyUrl = "/activity/metadata/standards", responseClass = ActivityMetadataPage.class) public ActivityMetadataPage metadataForStandards(@RequestParam(required = false) Long start, @RequestParam(required = false) Long end, @RequestParam(required = false) Integer pageNum, @RequestParam(required = false) Integer pageSize) throws JsonParseException, IOException, ValidationException { @@ -688,7 +671,6 @@ public ActivityMetadataPage metadataForStandards(@RequestParam(required = false) }) @RequestMapping(value = "/metadata/svaps", method = RequestMethod.GET, produces = "application/json; charset=utf-8") - @DeprecatedApiResponseFields(friendlyUrl = "/activity/metadata/svaps", responseClass = ActivityMetadataPage.class) public ActivityMetadataPage metadataForSvaps(@RequestParam(required = false) Long start, @RequestParam(required = false) Long end, @RequestParam(required = false) Integer pageNum, @RequestParam(required = false) Integer pageSize) throws JsonParseException, IOException, ValidationException { diff --git a/chpl/chpl-api/src/main/webapp/WEB-INF/web.xml b/chpl/chpl-api/src/main/webapp/WEB-INF/web.xml index fc9c765848..4cde1a8dd4 100644 --- a/chpl/chpl-api/src/main/webapp/WEB-INF/web.xml +++ b/chpl/chpl-api/src/main/webapp/WEB-INF/web.xml @@ -39,26 +39,4 @@ /ff4j-console/* /static/* - - - - quartz:config-file - quartz.properties - - - quartz:shutdown-on-unload - true - - - quartz:wait-on-shutdown - true - - - quartz:start-on-load - false - - - org.quartz.ee.servlet.QuartzInitializerListener - - diff --git a/chpl/chpl-resources/src/main/resources/environment.properties b/chpl/chpl-resources/src/main/resources/environment.properties index 813443e0e7..0f1a00c34c 100644 --- a/chpl/chpl-resources/src/main/resources/environment.properties +++ b/chpl/chpl-resources/src/main/resources/environment.properties @@ -17,7 +17,7 @@ chplUrlBegin=https://chpl.healthit.gov developerUrlPart=/#/organizations/developers/%s jndiName=java:comp/env/jdbc/openchpl persistenceUnitName=openchpl -api.version=47.6.0 +api.version=47.7.0 api.description=Created by CHPL Development Team. Please submit any questions using the Health IT \ Feedback Form and select the "Certified Health IT Products List (CHPL)" category.
\ See more at %s diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/CHPLServiceConfig.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/CHPLServiceConfig.java index bbaf7aa89b..0e267f697c 100644 --- a/chpl/chpl-service/src/main/java/gov/healthit/chpl/CHPLServiceConfig.java +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/CHPLServiceConfig.java @@ -27,8 +27,10 @@ import org.apache.http.conn.ssl.TrustStrategy; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.quartz.spi.JobFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.MethodInvokingFactoryBean; +import org.springframework.context.ApplicationContext; import org.springframework.context.EnvironmentAware; import org.springframework.context.MessageSource; import org.springframework.context.annotation.Bean; @@ -39,6 +41,7 @@ import org.springframework.context.annotation.PropertySources; import org.springframework.context.support.ResourceBundleMessageSource; import org.springframework.core.env.Environment; +import org.springframework.core.io.ClassPathResource; import org.springframework.core.task.TaskExecutor; import org.springframework.http.HttpRequest; import org.springframework.http.MediaType; @@ -52,6 +55,7 @@ import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; +import org.springframework.scheduling.quartz.SchedulerFactoryBean; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.web.client.RestTemplate; @@ -96,6 +100,9 @@ public class CHPLServiceConfig implements WebMvcConfigurer, EnvironmentAware { @Autowired private Environment env; + @Autowired + private ApplicationContext applicationContext; + @Override public void setEnvironment(final Environment environment) { this.env = environment; @@ -279,4 +286,21 @@ private int getRequestTimeout() { } return requestTimeout; } + + @Bean + public JobFactory jobFactory() { + QuartzJobFactory jobFactory = new QuartzJobFactory(applicationContext); + return jobFactory; + } + + @Bean + public SchedulerFactoryBean schedulerFactory() { + SchedulerFactoryBean factory = new SchedulerFactoryBean(); + factory.setAutoStartup(true); + factory.setConfigLocation(new ClassPathResource("quartz.properties")); + factory.setJobFactory(jobFactory()); + + return factory; + } + } diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/QuartzJobFactory.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/QuartzJobFactory.java new file mode 100644 index 0000000000..5991dfdb44 --- /dev/null +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/QuartzJobFactory.java @@ -0,0 +1,28 @@ +package gov.healthit.chpl; + +import org.quartz.spi.TriggerFiredBundle; +import org.springframework.aop.aspectj.annotation.AspectJProxyFactory; +import org.springframework.beans.factory.config.AutowireCapableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.scheduling.quartz.SpringBeanJobFactory; + +import gov.healthit.chpl.scheduler.JobAspect; + +public class QuartzJobFactory extends SpringBeanJobFactory { + private AutowireCapableBeanFactory beanFactory; + + public QuartzJobFactory(ApplicationContext applicationContext) { + beanFactory = applicationContext.getAutowireCapableBeanFactory(); + } + + @Override + protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception { + final Object job = super.createJobInstance(bundle); + beanFactory.autowireBean(job); + + AspectJProxyFactory pFactory = new AspectJProxyFactory(job); + pFactory.addAspect(new JobAspect()); + + return pFactory.getProxy(); + } +} diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/SpringContext.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/SpringContext.java index 032b97bb2e..05294f4f84 100644 --- a/chpl/chpl-service/src/main/java/gov/healthit/chpl/SpringContext.java +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/SpringContext.java @@ -3,10 +3,11 @@ import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; +import org.springframework.scheduling.quartz.SpringBeanJobFactory; import org.springframework.stereotype.Component; @Component -public class SpringContext implements ApplicationContextAware { +public class SpringContext extends SpringBeanJobFactory implements ApplicationContextAware { private static ApplicationContext context; diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/activity/ActivityMetadataBuilder.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/activity/ActivityMetadataBuilder.java index 112eff90d8..597eec1c7b 100644 --- a/chpl/chpl-service/src/main/java/gov/healthit/chpl/activity/ActivityMetadataBuilder.java +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/activity/ActivityMetadataBuilder.java @@ -45,7 +45,6 @@ protected void addConceptSpecificMetadata(ActivityDTO dto, ActivityMetadata meta protected void addGenericMetadata(ActivityDTO dto, ActivityMetadata metadata) { metadata.setId(dto.getId()); metadata.setDate(dto.getActivityDate()); - metadata.setObjectId(dto.getActivityObjectId()); metadata.setObject(ActivityObject.builder() .id(dto.getActivityObjectId()) .build()); diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/activity/DeveloperActivityMetadataBuilder.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/activity/DeveloperActivityMetadataBuilder.java index 0743b716d5..59da4d1923 100644 --- a/chpl/chpl-service/src/main/java/gov/healthit/chpl/activity/DeveloperActivityMetadataBuilder.java +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/activity/DeveloperActivityMetadataBuilder.java @@ -1,12 +1,9 @@ package gov.healthit.chpl.activity; -import java.util.List; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import com.fasterxml.jackson.databind.ObjectMapper; - +import gov.healthit.chpl.dao.DeveloperDAO; import gov.healthit.chpl.domain.Developer; import gov.healthit.chpl.domain.activity.ActivityCategory; import gov.healthit.chpl.domain.activity.ActivityMetadata; @@ -18,12 +15,14 @@ @Log4j2 @Component("developerActivityMetadataBuilder") public class DeveloperActivityMetadataBuilder extends ActivityMetadataBuilder { - private ObjectMapper jsonMapper; + + private DeveloperDAO developerDao; @Autowired - public DeveloperActivityMetadataBuilder(ChplUserToCognitoUserUtil chplUserToCognitoUserUtil) { + public DeveloperActivityMetadataBuilder(ChplUserToCognitoUserUtil chplUserToCognitoUserUtil, + DeveloperDAO developerDao) { super(chplUserToCognitoUserUtil); - jsonMapper = new ObjectMapper(); + this.developerDao = developerDao; } @Override @@ -31,114 +30,17 @@ protected void addConceptSpecificMetadata(final ActivityDTO activity, final Acti if (!(metadata instanceof DeveloperActivityMetadata)) { return; } - DeveloperActivityMetadata developerMetadata = (DeveloperActivityMetadata) metadata; - - //parse developer specific metadata - //for merges, the original data is a list of developers. - //for other developer activities it's just a single developer. - Developer origDeveloper = null; - List origDevelopers = null; - if (activity.getOriginalData() != null) { - try { - origDeveloper = - jsonMapper.readValue(activity.getOriginalData(), Developer.class); - } catch (final Exception ignore) { - } - - //if we couldn't parse it as a Developer - //try to parse it as a List. - if (origDeveloper == null) { - try { - origDevelopers = jsonMapper.readValue(activity.getOriginalData(), - jsonMapper.getTypeFactory().constructCollectionType(List.class, Developer.class)); - } catch (final Exception ignore) { - } - } - - //if the orig data is not a developer or a list, log an error - if (origDeveloper == null && origDevelopers == null) { - LOGGER.error("Could not parse activity ID " + activity.getId() + " original data as " - + "a Developer or List. JSON was: " + activity.getOriginalData()); - } - } - - Developer newDeveloper = null; - List newDevelopers = null; - if (activity.getNewData() != null) { - try { - newDeveloper = - jsonMapper.readValue(activity.getNewData(), Developer.class); - } catch (final Exception ignore) { - } - - //if we couldn't parse it as a Developer - //try to parse it as a List. - if (newDeveloper == null) { - try { - newDevelopers = jsonMapper.readValue(activity.getNewData(), - jsonMapper.getTypeFactory().constructCollectionType(List.class, Developer.class)); - } catch (final Exception ignore) { - } - } - - //if the new data is not a developer or a list, log an error - if (newDeveloper == null && newDevelopers == null) { - LOGGER.error("Could not parse activity ID " + activity.getId() + " new data as " - + "a Developer or List. JSON was: " + activity.getNewData()); - } - } - - if (newDeveloper != null && origDeveloper != null - && newDevelopers == null && origDevelopers == null) { - //if there is a single new developer and single original developer - //that means the activity was editing the developer - parseDeveloperMetadata(developerMetadata, newDeveloper); - } else if (origDeveloper != null && newDeveloper == null - && newDevelopers == null && origDevelopers == null) { - //if there is an original developer but no new developer - //then the developer was deleted - pull its info from the orig object - parseDeveloperMetadata(developerMetadata, origDeveloper); - } else if (newDeveloper != null && origDeveloper == null - && newDevelopers == null && origDevelopers == null) { - //if there is a new developer but no original developer - //then the developer was just created - parseDeveloperMetadata(developerMetadata, newDeveloper); - } else if (newDevelopers != null && origDeveloper != null - && newDeveloper == null && origDevelopers == null) { - //multiple new developers and a single original developer - //means the activity was a split - parseDeveloperMetadata(developerMetadata, activity, newDevelopers); - } else if (origDevelopers != null && newDeveloper != null - && origDeveloper == null && newDevelopers == null) { - //multiple original developers and a single new developer - //means the activity was a merge - parseDeveloperMetadata(developerMetadata, newDeveloper); - } + DeveloperActivityMetadata developerMetadata = (DeveloperActivityMetadata) metadata; developerMetadata.getCategories().add(ActivityCategory.DEVELOPER); - } - private void parseDeveloperMetadata(DeveloperActivityMetadata developerMetadata, Developer developer) { - developerMetadata.setDeveloperName(developer.getName()); - developerMetadata.getObject().setName(developer.getName()); - developerMetadata.setDeveloperCode(developer.getDeveloperCode()); - } - - /** - * Find the developer in the list that matches the id of the developer - * the activity was recorded for. Parse activity metadata from that developer. - * @param developerMetadata - * @param activity - * @param developers - */ - private void parseDeveloperMetadata( - DeveloperActivityMetadata developerMetadata, ActivityDTO activity, - List developers) { - Long idToFind = activity.getActivityObjectId(); - for (Developer currDev : developers) { - if (currDev != null && currDev.getId().equals(idToFind)) { - parseDeveloperMetadata(developerMetadata, currDev); - break; + if (metadata.getObject() != null && metadata.getObject().getId() != null) { + Developer dev = null; + try { + dev = developerDao.getById(metadata.getObject().getId(), true); + metadata.getObject().setName(dev.getName()); + } catch (Exception ex) { + LOGGER.error("Could not find developer " + metadata.getObject().getId() + " for activity metadata.", ex); } } } diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/activity/ListingActivityMetadataBuilder.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/activity/ListingActivityMetadataBuilder.java index ab0bcb68dc..098e2bfd04 100644 --- a/chpl/chpl-service/src/main/java/gov/healthit/chpl/activity/ListingActivityMetadataBuilder.java +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/activity/ListingActivityMetadataBuilder.java @@ -1,35 +1,28 @@ package gov.healthit.chpl.activity; -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.collections4.MapUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import com.fasterxml.jackson.databind.ObjectMapper; - -import gov.healthit.chpl.certifiedproduct.service.CertificationStatusEventsService; -import gov.healthit.chpl.domain.CertifiedProductSearchDetails; import gov.healthit.chpl.domain.activity.ActivityCategory; import gov.healthit.chpl.domain.activity.ActivityMetadata; import gov.healthit.chpl.domain.activity.ListingActivityMetadata; -import gov.healthit.chpl.domain.surveillance.Surveillance; import gov.healthit.chpl.dto.ActivityDTO; +import gov.healthit.chpl.search.ListingSearchService; +import gov.healthit.chpl.search.domain.ListingSearchResult; import gov.healthit.chpl.util.ChplUserToCognitoUserUtil; +import lombok.extern.log4j.Log4j2; +@Log4j2 @Component("listingActivityMetadataBuilder") public class ListingActivityMetadataBuilder extends ActivityMetadataBuilder { - private static final Logger LOGGER = LogManager.getLogger(ListingActivityMetadataBuilder.class); - private CertificationStatusEventsService cseService; - private ObjectMapper jsonMapper; + private ListingSearchService listingSearchService; @Autowired - public ListingActivityMetadataBuilder(CertificationStatusEventsService cseService, ChplUserToCognitoUserUtil chplUserToCognitoUserUtil) { + public ListingActivityMetadataBuilder(ChplUserToCognitoUserUtil chplUserToCognitoUserUtil, + ListingSearchService listingSearchService) { super(chplUserToCognitoUserUtil); - this.cseService = cseService; - jsonMapper = new ObjectMapper(); + this.listingSearchService = listingSearchService; } @Override @@ -38,149 +31,15 @@ protected void addConceptSpecificMetadata(final ActivityDTO dto, final ActivityM return; } ListingActivityMetadata listingMetadata = (ListingActivityMetadata) metadata; - - //parse listing specific metadata - CertifiedProductSearchDetails origListing = null; - if (dto.getOriginalData() != null) { - try { - origListing = - jsonMapper.readValue(dto.getOriginalData(), CertifiedProductSearchDetails.class); - } catch (final Exception ex) { - LOGGER.error("Could not parse activity ID " + dto.getId() + " original data. " - + "JSON was: " + dto.getOriginalData(), ex); - } - } - - CertifiedProductSearchDetails newListing = null; - if (dto.getNewData() != null) { - try { - newListing = - jsonMapper.readValue(dto.getNewData(), CertifiedProductSearchDetails.class); - } catch (final Exception ex) { - LOGGER.error("Could not parse activity ID " + dto.getId() + " new data. " - + "JSON was: " + dto.getNewData(), ex); - } - } - - if (newListing != null) { - //for listing activity newListing should really never be null since listings can't be deleted - parseListingMetadata(listingMetadata, newListing); - } else if (origListing != null) { - //adding this here just in case in some future circumstance the newListing could have been null - parseListingMetadata(listingMetadata, origListing); - } - - categorizeActivity(listingMetadata, origListing, newListing); - } - - private void parseListingMetadata( - final ListingActivityMetadata listingMetadata, final CertifiedProductSearchDetails listing) { - listingMetadata.setChplProductNumber(listing.getChplProductNumber()); - listingMetadata.getObject().setName(listing.getChplProductNumber()); - if (listing.getCertifyingBody() != null - && listing.getCertifyingBody().get(CertifiedProductSearchDetails.ACB_NAME_KEY) != null - && listing.getCertifyingBody().get(CertifiedProductSearchDetails.ACB_ID_KEY) != null) { - listingMetadata.setAcbName(listing.getCertifyingBody().get(CertifiedProductSearchDetails.ACB_NAME_KEY).toString()); - listingMetadata.setAcbId(Long.valueOf(listing.getCertifyingBody().get(CertifiedProductSearchDetails.ACB_ID_KEY).toString())); - } - - //there is at least one activity record for listing ID 4801 - //that has a null certification date field due to a bug in the system at the time of the activity - listingMetadata.setCertificationDate(listing.getCertificationDate()); - if (listing.getDeveloper() != null) { - listingMetadata.setDeveloperName(listing.getDeveloper().getName()); - } - if (listing.getEdition() != null) { - listingMetadata.setEdition(listing.getEdition().getName()); - } else if (listing.getCertificationEdition() != null - && MapUtils.getString(listing.getCertificationEdition(), CertifiedProductSearchDetails.EDITION_NAME_KEY) != null) { - listingMetadata.setEdition(MapUtils.getString(listing.getCertificationEdition(), CertifiedProductSearchDetails.EDITION_NAME_KEY)); - } - if (listing.getCuresUpdate() != null) { - listingMetadata.setCuresUpdate(listing.getCuresUpdate()); - } - if (listing.getProduct() != null) { - listingMetadata.setProductName(listing.getProduct().getName()); - } - } - - private void categorizeActivity(final ListingActivityMetadata listingMetadata, - final CertifiedProductSearchDetails origListing, final CertifiedProductSearchDetails newListing) { listingMetadata.getCategories().add(ActivityCategory.LISTING); - if (origListing == null && newListing != null) { - listingMetadata.getCategories().add(ActivityCategory.LISTING_UPLOAD); - } else if (origListing != null && newListing != null) { - //status change? - if (origListing.getCertificationStatus() != null && newListing.getCertificationStatus() != null - && origListing.getCertificationStatus().getId() != newListing.getCertificationStatus().getId()) { - //check the legacy certificationStatus field for older activities - listingMetadata.getCategories().add(ActivityCategory.LISTING_STATUS_CHANGE); - } else if (!CollectionUtils.isEmpty(origListing.getCertificationEvents()) - && !CollectionUtils.isEmpty(newListing.getCertificationEvents()) - && (!CollectionUtils.isEmpty(cseService.getAddedCertificationStatusEvents(origListing, newListing)) - || !CollectionUtils.isEmpty(cseService.getRemovedCertificationStatusEvents(origListing, newListing)))) { - listingMetadata.getCategories().add(ActivityCategory.LISTING_STATUS_CHANGE); - } - //surveillance change? - //check for surveillance added or removed - if ((origListing.getSurveillance() != null && newListing.getSurveillance() == null) - || (origListing.getSurveillance() == null && newListing.getSurveillance() != null)) { - listingMetadata.getCategories().add(ActivityCategory.SURVEILLANCE); - } else if (origListing.getSurveillance() != null && newListing.getSurveillance() != null) { - if (origListing.getSurveillance().size() != newListing.getSurveillance().size()) { - listingMetadata.getCategories().add(ActivityCategory.SURVEILLANCE); - } else { - //there are the same amount of surveillances for both orig and - //new listing activity; - //check for new surveillance, deleted surveillance, or any updates - - //look for surveillance added - for (Surveillance newSurv : newListing.getSurveillance()) { - boolean foundInOrigListing = false; - for (Surveillance origSurv : origListing.getSurveillance()) { - if (origSurv.getId().longValue() == newSurv.getId().longValue()) { - foundInOrigListing = true; - } - } - if (!foundInOrigListing) { - //surv is in the new listing but not the original one = was added - listingMetadata.getCategories().add(ActivityCategory.SURVEILLANCE); - } - } - - //if there's a surveillance change already detected we don't need to look any farther - //if not keep looking for one - look for surveillance deleted - if (!listingMetadata.getCategories().contains(ActivityCategory.SURVEILLANCE)) { - for (Surveillance origSurv : origListing.getSurveillance()) { - boolean foundInNewListing = false; - for (Surveillance newSurv : newListing.getSurveillance()) { - if (origSurv.getId().longValue() == newSurv.getId().longValue()) { - foundInNewListing = true; - } - } - if (!foundInNewListing) { - //surv is in the original listing but not the new one = was deleted - listingMetadata.getCategories().add(ActivityCategory.SURVEILLANCE); - } - } - } - - //if there's a surveillance change already detected we don't need to look any farther - //if not keep looking for one - look for surveillance updated - if (!listingMetadata.getCategories().contains(ActivityCategory.SURVEILLANCE)) { - for (Surveillance origSurv : origListing.getSurveillance()) { - for (Surveillance newSurv : newListing.getSurveillance()) { - if (origSurv.getId().longValue() == newSurv.getId().longValue() - && !origSurv.matches(newSurv)) { - listingMetadata.getCategories().add(ActivityCategory.SURVEILLANCE); - //if we add a surveillance category there's no need to keep looking - //for more differences. - return; - } - } - } - } + if (metadata.getObject() != null && metadata.getObject().getId() != null) { + try { + ListingSearchResult listingSearchResult = listingSearchService.findListing(metadata.getObject().getId()); + if (listingSearchResult != null) { + metadata.getObject().setName(listingSearchResult.getChplProductNumber()); } + } catch (Exception ex) { + LOGGER.error("Could not find listing " + metadata.getObject().getId() + " for activity metadata.", ex); } } } diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/activity/ProductActivityMetadataBuilder.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/activity/ProductActivityMetadataBuilder.java index 3a3683811e..e33acc7004 100644 --- a/chpl/chpl-service/src/main/java/gov/healthit/chpl/activity/ProductActivityMetadataBuilder.java +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/activity/ProductActivityMetadataBuilder.java @@ -1,15 +1,9 @@ package gov.healthit.chpl.activity; -import java.util.List; - -import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import com.fasterxml.jackson.databind.ObjectMapper; - -import gov.healthit.chpl.dao.DeveloperDAO; -import gov.healthit.chpl.domain.Developer; +import gov.healthit.chpl.dao.ProductDAO; import gov.healthit.chpl.domain.Product; import gov.healthit.chpl.domain.activity.ActivityCategory; import gov.healthit.chpl.domain.activity.ActivityMetadata; @@ -21,14 +15,14 @@ @Log4j2 @Component("productActivityMetadataBuilder") public class ProductActivityMetadataBuilder extends ActivityMetadataBuilder { - private ObjectMapper jsonMapper; - private DeveloperDAO developerDao; + + private ProductDAO productDao; @Autowired - public ProductActivityMetadataBuilder(DeveloperDAO developerDao, ChplUserToCognitoUserUtil chplUserToCognitoUserUtil) { + public ProductActivityMetadataBuilder(ChplUserToCognitoUserUtil chplUserToCognitoUserUtil, + ProductDAO productDao) { super(chplUserToCognitoUserUtil); - jsonMapper = new ObjectMapper(); - this.developerDao = developerDao; + this.productDao = productDao; } @Override @@ -37,120 +31,15 @@ protected void addConceptSpecificMetadata(ActivityDTO activity, ActivityMetadata return; } ProductActivityMetadata productMetadata = (ProductActivityMetadata) metadata; - - //parse product specific metadata - //for merges, original data is a list of products - //for splits, new data is a list of products - //otherwise we expect orig/new data to be a single product - Product origProduct = null; - List origProducts = null; - if (activity.getOriginalData() != null) { - try { - origProduct = - jsonMapper.readValue(activity.getOriginalData(), Product.class); - } catch (Exception ignore) { } - - if (origProduct == null) { - try { - origProducts = jsonMapper.readValue(activity.getOriginalData(), - jsonMapper.getTypeFactory().constructCollectionType(List.class, Product.class)); - } catch (Exception ignore) { } - } - - if (origProduct == null && origProducts == null) { - LOGGER.error("Could not parse activity ID " + activity.getId() + " original data " - + " as ProductDTO or List. JSON was: " + activity.getOriginalData()); - } - } - - Product newProduct = null; - List newProducts = null; - if (activity.getNewData() != null) { - try { - newProduct = - jsonMapper.readValue(activity.getNewData(), Product.class); - } catch (Exception ignore) { } - - if (newProduct == null) { - try { - newProducts = jsonMapper.readValue(activity.getNewData(), - jsonMapper.getTypeFactory().constructCollectionType(List.class, Product.class)); - } catch (Exception ignore) { } - } - - if (newProduct == null && newProducts == null) { - LOGGER.error("Could not parse activity ID " + activity.getId() + " new data " - + "as ProductDTO or List. JSON was: " + activity.getNewData()); - } - } - - if (newProduct != null && origProduct != null - && newProducts == null && origProducts == null) { - //if there is a single new product and single original product - //that means the activity was editing the product - parseProductMetadata(productMetadata, newProduct); - } else if (origProduct != null && newProduct == null - && newProducts == null && origProducts == null) { - //if there is an original product but no new product - //then the product was deleted - pull its info from the orig object - parseProductMetadata(productMetadata, origProduct); - } else if (newProduct != null && origProduct == null - && newProducts == null && origProducts == null) { - //if there is a new product but no original product - //then the product was just created - parseProductMetadata(productMetadata, newProduct); - } else if (newProducts != null && origProduct != null - && newProduct == null && origProducts == null) { - //multiple new products and a single original product - //means the activity was a split - parseProductMetadata(productMetadata, activity, newProducts); - } else if (origProducts != null && newProduct != null - && origProduct == null && newProducts == null) { - //multiple original products and a single new product - //means the activity was a merge - parseProductMetadata(productMetadata, newProduct); - } - productMetadata.getCategories().add(ActivityCategory.PRODUCT); - } - private void parseProductMetadata( - ProductActivityMetadata productMetadata, Product product) { - //Developer id is always filled in the activity object - //but the name does not seem to be. If the name is available - //use it but if not look up the developer by ID - if (product.getOwner() != null && !StringUtils.isEmpty(product.getOwner().getName())) { - productMetadata.setDeveloperName(product.getOwner().getName()); - } else if (product.getOwner() != null && product.getOwner().getId() != null) { + if (metadata.getObject() != null && metadata.getObject().getId() != null) { + Product product = null; try { - Developer developer = developerDao.getSimpleDeveloperById(product.getOwner().getId(), true); - productMetadata.setDeveloperName(developer.getName()); + product = productDao.getById(metadata.getObject().getId(), false); + metadata.getObject().setName(product.getName()); } catch (Exception ex) { - LOGGER.error("Unable to find developer with ID " + product.getOwner().getId() + " referenced " - + "in activity for product " + product.getId()); - } - } else if (!StringUtils.isEmpty(product.getDeveloperName())) { - productMetadata.setDeveloperName(product.getDeveloperName()); - } else if (product.getDeveloperId() != null) { - try { - Developer developer = developerDao.getSimpleDeveloperById(product.getDeveloperId(), true); - productMetadata.setDeveloperName(developer.getName()); - } catch (Exception ex) { - LOGGER.error("Unable to find developer with ID " + product.getDeveloperId() + " referenced " - + "in activity for product " + product.getId()); - } - } - productMetadata.setProductName(product.getName()); - productMetadata.getObject().setName(product.getName()); - } - - private void parseProductMetadata(ProductActivityMetadata productMetadata, ActivityDTO activity, - List products) { - Long idToFind = activity.getActivityObjectId(); - for (Product currProduct : products) { - if (currProduct != null && currProduct.getId().equals(idToFind)) { - parseProductMetadata(productMetadata, currProduct); - break; + LOGGER.error("Could not find product " + metadata.getObject().getId() + " for activity metadata.", ex); } } } diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/domain/activity/ActivityMetadata.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/domain/activity/ActivityMetadata.java index 11a18b87fa..835a149faf 100644 --- a/chpl/chpl-service/src/main/java/gov/healthit/chpl/domain/activity/ActivityMetadata.java +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/domain/activity/ActivityMetadata.java @@ -6,7 +6,6 @@ import java.util.Objects; import java.util.Set; -import gov.healthit.chpl.api.deprecatedUsage.DeprecatedResponseField; import gov.healthit.chpl.domain.auth.User; import gov.healthit.chpl.util.Util; import lombok.AccessLevel; @@ -17,7 +16,6 @@ import lombok.NoArgsConstructor; import lombok.RequiredArgsConstructor; import lombok.Setter; -import lombok.Singular; import lombok.ToString; @Builder @@ -31,18 +29,16 @@ public class ActivityMetadata implements Serializable { private Long id; private ActivityConcept concept; - @Singular + + @Builder.Default private Set categories = new HashSet(); + @Setter(AccessLevel.NONE) @Getter(AccessLevel.NONE) private Date date; - @DeprecatedResponseField(message = "This field is deprecated and will be removed. Use object.id", - removalDate = "2024-10-31") - @Deprecated - private Long objectId; - private ActivityObject object; + private User responsibleUser; private String description; diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/domain/activity/ActivityMetadataPage.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/domain/activity/ActivityMetadataPage.java index 77f2bafadd..efc3e47360 100644 --- a/chpl/chpl-service/src/main/java/gov/healthit/chpl/domain/activity/ActivityMetadataPage.java +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/domain/activity/ActivityMetadataPage.java @@ -3,12 +3,6 @@ import java.io.Serializable; import java.util.Set; -/** - * A page of activity metadata including the page number, page size, - * and total result set size. - * @author kekey - * - */ public class ActivityMetadataPage implements Serializable { private static final long serialVersionUID = -3855142961571461535L; diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/domain/activity/DeveloperActivityMetadata.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/domain/activity/DeveloperActivityMetadata.java index 5971f212b5..5bfb967c2d 100644 --- a/chpl/chpl-service/src/main/java/gov/healthit/chpl/domain/activity/DeveloperActivityMetadata.java +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/domain/activity/DeveloperActivityMetadata.java @@ -1,5 +1,6 @@ package gov.healthit.chpl.domain.activity; +import gov.healthit.chpl.api.deprecatedUsage.DeprecatedResponseField; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -10,6 +11,11 @@ public class DeveloperActivityMetadata extends ActivityMetadata { private static final long serialVersionUID = 9069117187928313180L; + @Deprecated + @DeprecatedResponseField(message = "This field is deprecated and will be removed.", removalDate = "2025-06-01") private String developerName; + + @Deprecated + @DeprecatedResponseField(message = "This field is deprecated and will be removed.", removalDate = "2025-06-01") private String developerCode; } diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/domain/activity/ListingActivityMetadata.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/domain/activity/ListingActivityMetadata.java index dd1ed5e74c..bdb92526cd 100644 --- a/chpl/chpl-service/src/main/java/gov/healthit/chpl/domain/activity/ListingActivityMetadata.java +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/domain/activity/ListingActivityMetadata.java @@ -1,5 +1,6 @@ package gov.healthit.chpl.domain.activity; +import gov.healthit.chpl.api.deprecatedUsage.DeprecatedResponseField; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.Setter; @@ -12,12 +13,35 @@ public class ListingActivityMetadata extends ActivityMetadata { private static final long serialVersionUID = 5473773376581297578L; + @Deprecated + @DeprecatedResponseField(message = "This field is deprecated and will be removed.", removalDate = "2025-06-01") private String chplProductNumber; + + @Deprecated + @DeprecatedResponseField(message = "This field is deprecated and will be removed.", removalDate = "2025-06-01") private String acbName; + + @Deprecated + @DeprecatedResponseField(message = "This field is deprecated and will be removed.", removalDate = "2025-06-01") private Long acbId; + + @Deprecated + @DeprecatedResponseField(message = "This field is deprecated and will be removed.", removalDate = "2025-06-01") private String developerName; + + @Deprecated + @DeprecatedResponseField(message = "This field is deprecated and will be removed.", removalDate = "2025-06-01") private String productName; + + @Deprecated + @DeprecatedResponseField(message = "This field is deprecated and will be removed.", removalDate = "2025-06-01") private String edition; + + @Deprecated + @DeprecatedResponseField(message = "This field is deprecated and will be removed.", removalDate = "2025-06-01") private Boolean curesUpdate; + + @Deprecated + @DeprecatedResponseField(message = "This field is deprecated and will be removed.", removalDate = "2025-06-01") private Long certificationDate; } diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/domain/activity/ProductActivityMetadata.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/domain/activity/ProductActivityMetadata.java index 44044743b6..2b2a0f8b1c 100644 --- a/chpl/chpl-service/src/main/java/gov/healthit/chpl/domain/activity/ProductActivityMetadata.java +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/domain/activity/ProductActivityMetadata.java @@ -1,5 +1,6 @@ package gov.healthit.chpl.domain.activity; +import gov.healthit.chpl.api.deprecatedUsage.DeprecatedResponseField; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -10,7 +11,12 @@ public class ProductActivityMetadata extends ActivityMetadata { private static final long serialVersionUID = 9069117187924463180L; + @Deprecated + @DeprecatedResponseField(message = "This field is deprecated and will be removed.", removalDate = "2025-06-01") private String developerName; + + @Deprecated + @DeprecatedResponseField(message = "This field is deprecated and will be removed.", removalDate = "2025-06-01") private String productName; } diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/activity/GetActivityDetailsActionPermissions.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/activity/GetActivityDetailsActionPermissions.java index 7db210c0c1..b587b36e8b 100644 --- a/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/activity/GetActivityDetailsActionPermissions.java +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/activity/GetActivityDetailsActionPermissions.java @@ -130,7 +130,7 @@ public boolean hasAccess(Object obj) { case FUNCTIONALITY_TESTED: case SVAP: case STANDARD: - return false; + return getResourcePermissions().isUserRoleAcbAdmin(); default: // all other types of activity // are accessible to any logged-in or anonymous user diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/activity/GetFunctionalityTestedMetadataActionPermissions.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/activity/GetFunctionalityTestedMetadataActionPermissions.java index 89b5b172ec..7aaaa3cd75 100644 --- a/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/activity/GetFunctionalityTestedMetadataActionPermissions.java +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/activity/GetFunctionalityTestedMetadataActionPermissions.java @@ -8,11 +8,13 @@ public class GetFunctionalityTestedMetadataActionPermissions extends ActionPermissions { @Override public boolean hasAccess() { - return getResourcePermissions().isUserRoleAdmin() || getResourcePermissions().isUserRoleOnc(); + return getResourcePermissions().isUserRoleAdmin() || getResourcePermissions().isUserRoleOnc() + || getResourcePermissions().isUserRoleAcbAdmin(); } @Override public boolean hasAccess(Object obj) { - return getResourcePermissions().isUserRoleAdmin() || getResourcePermissions().isUserRoleOnc(); + return getResourcePermissions().isUserRoleAdmin() || getResourcePermissions().isUserRoleOnc() + || getResourcePermissions().isUserRoleAcbAdmin(); } } diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/activity/GetStandardMetadataActionPermissions.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/activity/GetStandardMetadataActionPermissions.java index 8feb5a384d..65a0409f73 100644 --- a/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/activity/GetStandardMetadataActionPermissions.java +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/activity/GetStandardMetadataActionPermissions.java @@ -8,11 +8,13 @@ public class GetStandardMetadataActionPermissions extends ActionPermissions { @Override public boolean hasAccess() { - return getResourcePermissions().isUserRoleAdmin() || getResourcePermissions().isUserRoleOnc(); + return getResourcePermissions().isUserRoleAdmin() || getResourcePermissions().isUserRoleOnc() + || getResourcePermissions().isUserRoleAcbAdmin(); } @Override public boolean hasAccess(Object obj) { - return getResourcePermissions().isUserRoleAdmin() || getResourcePermissions().isUserRoleOnc(); + return getResourcePermissions().isUserRoleAdmin() || getResourcePermissions().isUserRoleOnc() + || getResourcePermissions().isUserRoleAcbAdmin(); } } diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/activity/GetSvapMetadataActionPermissions.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/activity/GetSvapMetadataActionPermissions.java index 336967b735..5ebf1b47bf 100644 --- a/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/activity/GetSvapMetadataActionPermissions.java +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/activity/GetSvapMetadataActionPermissions.java @@ -8,11 +8,13 @@ public class GetSvapMetadataActionPermissions extends ActionPermissions { @Override public boolean hasAccess() { - return getResourcePermissions().isUserRoleAdmin() || getResourcePermissions().isUserRoleOnc(); + return getResourcePermissions().isUserRoleAdmin() || getResourcePermissions().isUserRoleOnc() + || getResourcePermissions().isUserRoleAcbAdmin(); } @Override public boolean hasAccess(Object obj) { - return getResourcePermissions().isUserRoleAdmin() || getResourcePermissions().isUserRoleOnc(); + return getResourcePermissions().isUserRoleAdmin() || getResourcePermissions().isUserRoleOnc() + || getResourcePermissions().isUserRoleAcbAdmin(); } } diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/functionalitytested/CreateActionPermissions.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/functionalitytested/CreateActionPermissions.java index 00c9697099..e76e27d106 100644 --- a/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/functionalitytested/CreateActionPermissions.java +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/functionalitytested/CreateActionPermissions.java @@ -8,7 +8,8 @@ public class CreateActionPermissions extends ActionPermissions { @Override public boolean hasAccess() { - return getResourcePermissions().isUserRoleAdmin(); + return getResourcePermissions().isUserRoleAdmin() + || getResourcePermissions().isUserRoleOnc(); } @Override diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/functionalitytested/DeleteActionPermissions.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/functionalitytested/DeleteActionPermissions.java index b67478e7fd..bcffcf6f13 100644 --- a/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/functionalitytested/DeleteActionPermissions.java +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/functionalitytested/DeleteActionPermissions.java @@ -9,7 +9,8 @@ public class DeleteActionPermissions extends ActionPermissions { @Override public boolean hasAccess() { - return getResourcePermissions().isUserRoleAdmin(); + return getResourcePermissions().isUserRoleAdmin() + || getResourcePermissions().isUserRoleOnc(); } @Override diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/functionalitytested/UpdateActionPermissions.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/functionalitytested/UpdateActionPermissions.java index 75a39f679a..ecd2365cf1 100644 --- a/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/functionalitytested/UpdateActionPermissions.java +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/functionalitytested/UpdateActionPermissions.java @@ -9,7 +9,8 @@ public class UpdateActionPermissions extends ActionPermissions { @Override public boolean hasAccess() { - return getResourcePermissions().isUserRoleAdmin(); + return getResourcePermissions().isUserRoleAdmin() + || getResourcePermissions().isUserRoleOnc(); } @Override diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/standard/CreateActionPermissions.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/standard/CreateActionPermissions.java index 105b406779..b89d96ceba 100644 --- a/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/standard/CreateActionPermissions.java +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/standard/CreateActionPermissions.java @@ -8,7 +8,8 @@ public class CreateActionPermissions extends ActionPermissions { @Override public boolean hasAccess() { - return getResourcePermissions().isUserRoleAdmin(); + return getResourcePermissions().isUserRoleAdmin() + || getResourcePermissions().isUserRoleOnc(); } @Override diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/standard/DeleteActionPermissions.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/standard/DeleteActionPermissions.java index fc68749436..4d5959e1f2 100644 --- a/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/standard/DeleteActionPermissions.java +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/standard/DeleteActionPermissions.java @@ -9,7 +9,8 @@ public class DeleteActionPermissions extends ActionPermissions { @Override public boolean hasAccess() { - return getResourcePermissions().isUserRoleAdmin(); + return getResourcePermissions().isUserRoleAdmin() + || getResourcePermissions().isUserRoleOnc(); } @Override diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/standard/UpdateActionPermissions.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/standard/UpdateActionPermissions.java index 35e460648c..3856f606bb 100644 --- a/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/standard/UpdateActionPermissions.java +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/standard/UpdateActionPermissions.java @@ -9,7 +9,8 @@ public class UpdateActionPermissions extends ActionPermissions { @Override public boolean hasAccess() { - return getResourcePermissions().isUserRoleAdmin(); + return getResourcePermissions().isUserRoleAdmin() + || getResourcePermissions().isUserRoleOnc(); } @Override diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/testtool/CreateActionPermissions.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/testtool/CreateActionPermissions.java index 4154876b9b..dec5835d1a 100644 --- a/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/testtool/CreateActionPermissions.java +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/testtool/CreateActionPermissions.java @@ -8,7 +8,8 @@ public class CreateActionPermissions extends ActionPermissions { @Override public boolean hasAccess() { - return getResourcePermissions().isUserRoleAdmin(); + return getResourcePermissions().isUserRoleAdmin() + || getResourcePermissions().isUserRoleOnc(); } @Override diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/testtool/DeleteActionPermissions.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/testtool/DeleteActionPermissions.java index bd9aa519f5..2c19bd0188 100644 --- a/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/testtool/DeleteActionPermissions.java +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/testtool/DeleteActionPermissions.java @@ -9,7 +9,8 @@ public class DeleteActionPermissions extends ActionPermissions { @Override public boolean hasAccess() { - return getResourcePermissions().isUserRoleAdmin(); + return getResourcePermissions().isUserRoleAdmin() + || getResourcePermissions().isUserRoleOnc(); } @Override diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/testtool/UpdateActionPermissions.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/testtool/UpdateActionPermissions.java index 32aa85b7df..7b0ceb7957 100644 --- a/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/testtool/UpdateActionPermissions.java +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/testtool/UpdateActionPermissions.java @@ -9,7 +9,8 @@ public class UpdateActionPermissions extends ActionPermissions { @Override public boolean hasAccess() { - return getResourcePermissions().isUserRoleAdmin(); + return getResourcePermissions().isUserRoleAdmin() + || getResourcePermissions().isUserRoleOnc(); } @Override diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/scheduler/ChplSchedulerReference.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/scheduler/ChplSchedulerReference.java index 59b1880c51..9de02c5e93 100644 --- a/chpl/chpl-service/src/main/java/gov/healthit/chpl/scheduler/ChplSchedulerReference.java +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/scheduler/ChplSchedulerReference.java @@ -1,11 +1,9 @@ package gov.healthit.chpl.scheduler; -import jakarta.annotation.PostConstruct; - import org.quartz.Scheduler; -import org.quartz.SchedulerException; -import org.quartz.impl.StdSchedulerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; +import org.springframework.scheduling.quartz.SchedulerFactoryBean; import org.springframework.stereotype.Component; /** @@ -18,15 +16,9 @@ public class ChplSchedulerReference { private Scheduler scheduler; - /** - * Initializes the Quartz Scheduler when this object is created. - * @throws SchedulerException if thrown - */ - @PostConstruct - public void init() throws SchedulerException { - StdSchedulerFactory sf = new StdSchedulerFactory(); - sf.initialize(); - this.scheduler = sf.getScheduler(); + @Autowired + public ChplSchedulerReference(SchedulerFactoryBean schedulerFactory) { + this.scheduler = schedulerFactory.getScheduler(); } public Scheduler getScheduler() { diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/scheduler/JobAspect.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/scheduler/JobAspect.java new file mode 100644 index 0000000000..d09bfda06d --- /dev/null +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/scheduler/JobAspect.java @@ -0,0 +1,16 @@ +package gov.healthit.chpl.scheduler; + +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.After; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.security.core.context.SecurityContextHolder; + +@Aspect +public class JobAspect { + + @After("execution(public void org.quartz.Job.execute(..))") + public void afterExecute(JoinPoint joinPoint) { + SecurityContextHolder.clearContext(); + } + +} diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/scheduler/job/QuartzJob.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/scheduler/job/QuartzJob.java index 3677a0347e..e7838e1137 100644 --- a/chpl/chpl-service/src/main/java/gov/healthit/chpl/scheduler/job/QuartzJob.java +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/scheduler/job/QuartzJob.java @@ -8,7 +8,9 @@ import org.springframework.core.env.Environment; import gov.healthit.chpl.scheduler.AuthenticatedUserAwareJob; +import lombok.extern.log4j.Log4j2; +@Log4j2 public abstract class QuartzJob extends AuthenticatedUserAwareJob implements Job { public static final String JOB_DATA_KEY_EMAIL = "email"; public static final String JOB_DATA_KEY_ACB = "acb"; diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/scheduler/job/downloadfile/GenerateListingDownloadFilesAspect.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/scheduler/job/downloadfile/GenerateListingDownloadFilesAspect.java index d6c366a0de..eaf285ad87 100644 --- a/chpl/chpl-service/src/main/java/gov/healthit/chpl/scheduler/job/downloadfile/GenerateListingDownloadFilesAspect.java +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/scheduler/job/downloadfile/GenerateListingDownloadFilesAspect.java @@ -64,15 +64,20 @@ private void scheduleDownloadFileJob(ListingSet listingSet) { if (!isJobAlreadyScheduled(info)) { ChplOneTimeTrigger downloadFileTrigger = new ChplOneTimeTrigger(); - ChplJob downloadFileJob = getDownloadFileJob(listingSetToJobNameMap.get(listingSet).jobName); - downloadFileTrigger.setJob(downloadFileJob); - downloadFileTrigger.setRunDateMillis(listingSetToJobNameMap.get(listingSet).getRunDateTime().toInstant().toEpochMilli()); - downloadFileTrigger = addTriggerToScheduler(downloadFileTrigger); - - LOGGER.info("System job {}/{} has been scheduled for {}", - downloadFileTrigger.getJob().getGroup(), - downloadFileTrigger.getJob().getName(), - DateUtil.toLocalDateTime(downloadFileTrigger.getRunDateMillis()).toString()); + String downloadFileJobName = listingSetToJobNameMap.get(listingSet).jobName; + ChplJob downloadFileJob = getDownloadFileJob(downloadFileJobName); + if (downloadFileJob != null) { + downloadFileTrigger.setJob(downloadFileJob); + downloadFileTrigger.setRunDateMillis(listingSetToJobNameMap.get(listingSet).getRunDateTime().toInstant().toEpochMilli()); + downloadFileTrigger = addTriggerToScheduler(downloadFileTrigger); + + LOGGER.info("System job {}/{} has been scheduled for {}", + downloadFileTrigger.getJob().getGroup(), + downloadFileTrigger.getJob().getName(), + DateUtil.toLocalDateTime(downloadFileTrigger.getRunDateMillis()).toString()); + } else { + LOGGER.error("No job found with name " + downloadFileJobName); + } } } @@ -89,7 +94,7 @@ private ChplJob getDownloadFileJob(String jobName) { return getAllJobs().stream() .filter(job -> job.getName().equals(jobName)) .findAny() - .get(); + .orElse(null); } private List getAllJobs() { diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/user/cognito/CognitoApiWrapper.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/user/cognito/CognitoApiWrapper.java index 833a545ea8..9e36e313a1 100644 --- a/chpl/chpl-service/src/main/java/gov/healthit/chpl/user/cognito/CognitoApiWrapper.java +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/user/cognito/CognitoApiWrapper.java @@ -173,24 +173,28 @@ public AuthenticationResultType respondToNewPasswordRequiredChallenge(CognitoNew } } - @Cacheable(CacheNames.COGNITO_USERS_BY_UUID) + @Cacheable(value = CacheNames.COGNITO_USERS_BY_UUID, unless = "#result == null") public User getUserInfo(UUID cognitoId) throws UserRetrievalException { AdminGetUserRequest request = AdminGetUserRequest.builder() .userPoolId(userPoolId) .username(cognitoId.toString()) .build(); - AdminGetUserResponse response = cognitoClient.adminGetUser(request); - if (response == null || response.sdkHttpResponse() == null || !response.sdkHttpResponse().isSuccessful()) { - return null; - } - - User user = createUserFromGetUserResponse(response); - List groupsForUser = getGroupsForUser(user.getEmail()); - if (!doesGroupMatchCurrentEnvironment(groupsForUser)) { + try { + AdminGetUserResponse response = cognitoClient.adminGetUser(request); + if (response == null || response.sdkHttpResponse() == null || !response.sdkHttpResponse().isSuccessful()) { + return null; + } + User user = createUserFromGetUserResponse(response); + List groupsForUser = getGroupsForUser(user.getEmail()); + if (!doesGroupMatchCurrentEnvironment(groupsForUser)) { + return null; + } + return user; + } catch (Exception e) { + LOGGER.error("Unable to get user " + cognitoId.toString() + " with AdminGetUserRequest", e); return null; } - return user; } @Cacheable(value = CacheNames.COGNITO_USERS_BY_EMAIL, unless = "#result == null") @@ -289,7 +293,7 @@ public CognitoCredentials reenableUser(User existingUser) throws UserCreationExc public AuthenticationResultType refreshToken(String refreshToken, UUID cognitoId) { Map authParams = new LinkedHashMap(); authParams.put("REFRESH_TOKEN", refreshToken); - authParams.put("SECRET_HASH", calculateSecretHash(cognitoId.toString())); + authParams.put("SECRET_HASH", calculateSecretHash(cognitoId.toString())); AdminInitiateAuthRequest authRequest = AdminInitiateAuthRequest.builder() .authFlow(AuthFlowType.REFRESH_TOKEN_AUTH)