Skip to content

Fix: missing staged meds when using save and print functionality with multiple different patient Rx related pages (Medications, Allergies) open - LEGACY BUG#2261

Open
LiamStanziani wants to merge 18 commits intodevelopfrom
bug/missing-meds-when-saving
Open

Fix: missing staged meds when using save and print functionality with multiple different patient Rx related pages (Medications, Allergies) open - LEGACY BUG#2261
LiamStanziani wants to merge 18 commits intodevelopfrom
bug/missing-meds-when-saving

Conversation

@LiamStanziani
Copy link
Copy Markdown
Collaborator

@LiamStanziani LiamStanziani commented Feb 3, 2026

In this PR, I have fixed:

  • Missing meds when saving the staged meds (happens with multiple Rx sessions overwriting each other)
  • General code upgrades (Encoding, error handling)

I have tested this by:

  • Creating medications, searching for medications, having multiple instances of Rx tabs open, Save & Print functionality

User description

Summary by Sourcery

Implement per-patient prescription session handling and multi-tab safety across the Rx workflow to keep medications tied to the correct patient and avoid losing staged prescriptions.

Bug Fixes:

  • Ensure prescriptions and drug lists remain associated with the correct patient when multiple Medications tabs or windows are open by keying Rx sessions per demographic.
  • Prevent loss of staged prescriptions after Save & Print by clearing the stash reliably on close and handling lightwindow closures safely.
  • Return clear 400 errors when an invalid or missing prescription identifier is submitted during drug updates, and improve logging for empty special instructions.

Enhancements:

  • Introduce RxSessionBean helpers and RxSessionFilter to manage per-patient Rx session beans while preserving legacy session key behavior.
  • Add a client-side rxSessionInterceptor that injects demographicNo into Rx-related AJAX calls, forms, and iframes for accurate server-side patient context.
  • Update Rx JSPs and messenger preview generation to propagate demographicNo through requests and use it for patient lookup instead of relying on shared session attributes.

Summary by cubic

Fixes missing or cross‑patient meds by isolating Rx sessions per patient and passing demographicNo across all requests so multiple tabs are safe. Save & Print, Allergies, and messenger preview now always use the right patient.

  • New Features

    • Per‑patient RxSessionBean with saveToSession and legacy fallback; used across Rx actions and JSPs.
    • RxSessionFilter runs before Struts2 for /oscarRx/*, CaseManagementView.do, and messenger preview; swaps the correct bean and Patient per request; accepts demographicNo/demographic_no.
    • rxSessionInterceptor.js injects demographicNo into Prototype, jQuery, fetch (preserves Request objects), and Rx forms; ViewScript* and SearchDrug3 pass it through iframes and posts.
  • Bug Fixes

    • Prescriptions and drug lists stay with the correct patient across tabs; staged meds persist through Save & Print and clear only on close.
    • Safer updates: invalid/missing randomId returns 400 JSON; supports String binding for demographicNo; stricter parsing in actions/JSPs.
    • Stops cross‑patient leakage when the param is missing by clearing stale legacy beans and syncing the session Patient.

Written for commit 910f52c. Summary will update on new commits.

Summary by Sourcery

Implement per-patient prescription session handling keyed by demographicNo to make Rx workflows safe across multiple tabs and windows and prevent cross-patient contamination.

Bug Fixes:

  • Validate and handle invalid or missing prescription identifiers when updating drugs, returning clear 400 responses instead of failing silently.
  • Prevent loss or cross-contamination of prescriptions and drug profiles when multiple Medications-related tabs are open by tying Rx session and patient lookup to demographicNo.
  • Ensure staged prescriptions are cleared only on close via updated stash reset behavior in ViewScript pages, avoiding unintended data loss.

Enhancements:

  • Add RxSessionBean helpers and an RxSessionFilter servlet filter to manage per-patient Rx session beans while maintaining legacy session key compatibility.
  • Introduce a client-side rxSessionInterceptor that injects demographicNo into Rx-related AJAX calls, forms, and fetch requests for consistent patient context.
  • Update Rx JSPs and messenger preview generation to propagate demographicNo through requests and use it for patient lookup instead of relying solely on shared session attributes.
  • Simplify logging for empty or short drug special instructions for clearer diagnostics.

Build:

  • Register RxSessionFilter in web.xml for Rx, case management, and messenger preview endpoints to enable per-request session isolation.

Summary by CodeRabbit

  • New Features

    • Enhanced multi-tab prescription management—users can now simultaneously work with prescriptions for multiple patients across different browser tabs without experiencing session conflicts or data interference.
  • Bug Fixes

    • Improved error handling and validation throughout prescription workflows. Better error messages and graceful recovery for edge cases, including improved handling of missing or incomplete prescription data.

PR Type

Bug fix, Enhancement


Description

  • Implement per-patient RxSessionBean storage with demographicNo-based session keys to prevent medication loss across multiple patient tabs

  • Add RxSessionFilter servlet filter to swap correct patient bean per request, enabling multi-tab prescription safety

  • Introduce rxSessionInterceptor.js to inject demographicNo into AJAX calls, forms, and iframes for consistent patient context

  • Improve error handling in prescription workflows with clearer validation and error messages for missing/invalid data


Diagram Walkthrough

flowchart LR
  A["Request with demographicNo"] -->|RxSessionFilter| B["Lookup per-patient RxSessionBean"]
  B -->|Found| C["Swap into legacy session key"]
  B -->|Not found| D["Use fallback bean"]
  C -->|Available to| E["Actions & JSPs"]
  D -->|Available to| E
  F["rxSessionInterceptor.js"] -->|Injects demographicNo| G["AJAX calls & forms"]
  G -->|Propagates to| H["Server-side filter"]
  H -->|Ensures| I["Correct patient context"]
Loading

File Walkthrough

Relevant files
Enhancement
12 files
RxSessionBean.java
Add per-patient session key helpers and storage methods   
+81/-0   
RxSessionFilter.java
New servlet filter for multi-patient tab session isolation
+113/-0 
RxChoosePatient2Action.java
Update to use per-patient RxSessionBean retrieval               
+13/-4   
RxShowAllergy2Action.java
Refactor bean initialization with per-patient session support
+12/-12 
CaseManagementView2Action.java
Update RxSessionBean initialization with per-patient keys
+14/-4   
RxPrescriptionData.java
Simplify special instructions logging with clearer format
+4/-8     
rxSessionInterceptor.js
New AJAX interceptor to propagate demographicNo across requests
+108/-0 
ListDrugs.jsp
Enhance patient data retrieval with demographicNo parameter support
+28/-1   
SearchDrug3.jsp
Add rxSessionInterceptor and improve lightwindow close handling
+29/-7   
ViewScript.jsp
Include rxSessionInterceptor and add demographicNo to iframe/form
+11/-3   
ViewScript2.jsp
Add rxSessionInterceptor and implement stash clearing on close
+27/-3   
generatePreviewPDF.jsp
Update RxSessionBean initialization with per-patient session support
+12/-9   
Bug fix
1 files
RxWriteScript2Action.java
Add validation and error handling for missing prescriptions
+37/-4   
Configuration changes
1 files
web.xml
Register RxSessionFilter for Rx-related URL patterns         
+18/-1   
Formatting
1 files
struts.xml
Minor formatting adjustment to struts configuration           
+1/-0     

…eeded for fixes to this issue when reproducing the workflow
…ate as needed for fixes to this issue when reproducing the workflow"

This reverts commit 8d3b9b7.
…providers, will need to update to iron out bugs and less memory usage
…working fully, but works for most actions inside of the Medications module
…icNo and there was no per-patient session bean for the connected demographicNo, meaning a bean was never created in the first place
@LiamStanziani LiamStanziani self-assigned this Feb 3, 2026
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai bot commented Feb 3, 2026

Reviewer's Guide

Implements per-patient Rx session handling (keyed by demographicNo) plus a request filter and JS interceptor so all Rx requests resolve the correct RxSessionBean, updates JSPs/actions to propagate demographicNo, hardens error handling around prescription updates, and ensures the staged prescription stash is reliably cleared on close instead of being lost mid-flow.

Sequence diagram for_Rx_request_with_multi_tab_session_isolation

sequenceDiagram
  actor User
  participant Browser
  participant rxSessionInterceptor_js
  participant RxSessionFilter
  participant HttpSession
  participant RxSessionBean
  participant RxWriteScript2Action

  User->>Browser: Click update quantity in Medications tab
  Browser->>rxSessionInterceptor_js: Prepare AJAX request
  rxSessionInterceptor_js->>Browser: Attach demographicNo to request
  Browser->>RxSessionFilter: HTTP POST /oscarRx/updateDrug.do

  RxSessionFilter->>HttpSession: getAttribute(LEGACY_KEY)
  RxSessionFilter->>RxSessionBean: getSessionKey(demographicNo)
  RxSessionFilter->>HttpSession: getAttribute(RxSessionBean_<demographicNo>)
  alt per_patient_bean_found
    RxSessionFilter->>HttpSession: setAttribute(LEGACY_KEY, perPatientBean)
  else no_bean_and_explicit_demographicNo
    RxSessionFilter->>HttpSession: removeAttribute(LEGACY_KEY)
  end
  RxSessionFilter-->>Browser: continue filter chain

  Browser->>RxWriteScript2Action: dispatch to updateDrug()
  RxWriteScript2Action->>HttpSession: getAttribute(LEGACY_KEY) as bean
  RxWriteScript2Action->>RxSessionBean: getStashItem2(randomIdInt)
  alt prescription_found
    RxWriteScript2Action-->>Browser: 200 OK JSON (updated)
  else invalid_randomId
    RxWriteScript2Action-->>Browser: 400 JSON {error: Invalid prescription identifier}
  else prescription_missing
    RxWriteScript2Action-->>Browser: 400 JSON {error: Prescription not found}
  end
Loading

Class diagram for per_patient_Rx_session_handling

classDiagram

class RxSessionBean {
  - Logger logger
  - String SESSION_KEY_PREFIX
  - String LEGACY_SESSION_KEY
  - String providerNo
  - int demographicNo
  + static String getSessionKey(int demographicNo)
  + static RxSessionBean getFromSession(HttpSession session, int demographicNo)
  + static RxSessionBean getFromSession(HttpServletRequest request, int demographicNo)
  + static void saveToSession(HttpSession session, RxSessionBean bean)
  + static void saveToSession(HttpServletRequest request, RxSessionBean bean)
  + int getDemographicNo()
  + void setDemographicNo(String RHS)
  + String getProviderNo()
  + void setProviderNo(String providerNo)
}

class RxSessionFilter {
  - Logger logger
  - String LEGACY_KEY
  + void init(FilterConfig filterConfig)
  + void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
  + void destroy()
  - static int parseDemographicNo(String param)
}

class RxWriteScript2Action {
  + String updateDrug()
  - HttpServletRequest request
  - HttpServletResponse response
  - ObjectMapper objectMapper
  - RxSessionBean bean
}

class RxShowAllergy2Action {
  + String execute()
  - HttpServletRequest request
  - String user_no
}

class RxChoosePatient2Action {
  + String execute()
  + String getDemographicNo()
  - HttpServletRequest request
  - String user_no
}

class CaseManagementView2Action {
  + String view()
  - HttpServletRequest request
  - String demoNo
  - Logger logger
}

class RxPrescriptionData {
  + boolean Save(String scriptId)
  - String special
}

class Prescription

RxSessionFilter --> RxSessionBean : uses
RxWriteScript2Action --> RxSessionBean : uses
RxShowAllergy2Action --> RxSessionBean : uses
RxChoosePatient2Action --> RxSessionBean : uses
CaseManagementView2Action --> RxSessionBean : uses
RxWriteScript2Action --> RxPrescriptionData : updates Prescription
RxSessionBean .. RxPrescriptionData : holds staged prescriptions
RxPrescriptionData *-- Prescription : contains
Loading

File-Level Changes

Change Details Files
Introduce per-patient RxSessionBean storage helpers and a servlet filter to safely select the correct patient session in multi-tab scenarios while preserving legacy behaviour.
  • Added helper methods on RxSessionBean to compute per-patient session keys, retrieve beans by demographicNo (with legacy key migration), and save beans to both per-patient and legacy keys.
  • Implemented RxSessionFilter to read demographicNo from requests, swap the matching per-patient RxSessionBean into the legacy session key before processing, and clear the legacy key when an explicit demographicNo has no corresponding bean.
  • Registered RxSessionFilter in web.xml for /oscarRx/*, CaseManagementView.do, and messenger/generatePreviewPDF.jsp so all relevant Rx workflows go through the new selection logic.
src/main/java/ca/openosp/openo/prescript/pageUtil/RxSessionBean.java
src/main/java/ca/openosp/openo/prescript/pageUtil/RxSessionFilter.java
src/main/webapp/WEB-INF/web.xml
Update server-side actions and JSP flows to use demographicNo-aware RxSessionBean access and patient lookup instead of relying solely on the legacy shared session attributes.
  • Refactored RxShowAllergy2Action, RxChoosePatient2Action, and CaseManagementView2Action to parse demographicNo safely, fetch or create per-patient RxSessionBeans via the new helpers, and persist them using saveToSession.
  • Adjusted generatePreviewPDF.jsp to resolve the RxSessionBean per demographic_no, set provider/demographic context, and store via saveToSession while still populating patient context in the session.
  • Changed ListDrugs.jsp to prefer demographicNo from the request, then from the bean, and only finally fall back to the session Patient attribute when loading patient drug data.
src/main/java/ca/openosp/openo/prescript/pageUtil/RxShowAllergy2Action.java
src/main/java/ca/openosp/openo/prescript/pageUtil/RxChoosePatient2Action.java
src/main/java/ca/openosp/openo/casemgmt/web/CaseManagementView2Action.java
src/main/webapp/messenger/generatePreviewPDF.jsp
src/main/webapp/oscarRx/ListDrugs.jsp
Add a client-side rxSessionInterceptor to propagate demographicNo through Rx-related AJAX calls, fetch requests, and forms, and wire it into key Rx JSPs including search and script views.
  • Created rxSessionInterceptor.js that inspects Prototype Ajax.Request/Updater, jQuery.ajax, fetch, and Rx-related forms, injecting demographicNo when missing so the filter can select the correct RxSessionBean.
  • Updated SearchDrug3.jsp to expose currentDemographicNo to JS, include the interceptor script, ensure hidden demographicNo fields use the correct value, and append demographicNo when opening the ViewScript2 window.
  • Updated ViewScript.jsp and ViewScript2.jsp to set currentDemographicNo, include the interceptor, pass demographicNo into preview iframes, and include demographicNo in the clearPending form submissions.
src/main/webapp/oscarRx/js/rxSessionInterceptor.js
src/main/webapp/oscarRx/SearchDrug3.jsp
src/main/webapp/oscarRx/ViewScript.jsp
src/main/webapp/oscarRx/ViewScript2.jsp
Improve reliability of the Save & Print flow by clearing the staged prescription stash only on explicit close, and by tightening validation around prescription updates.
  • Added resetStashAndClose helper in ViewScript.jsp and ViewScript2.jsp to POST clearStash (and clearReRxDrugList in ViewScript2) before closing the lightwindow, and rewired Back to Oscar buttons to use it instead of directly closing.
  • Enhanced RxWriteScript2Action.updateDrug to validate randomId as an integer, return structured 400 JSON errors for invalid or missing prescriptions, and log both cases clearly.
  • Changed RxWriteScript2Action.setDemographicNo to accept a String from Struts2 binding and parse it safely, ignoring invalid values rather than throwing.
  • Left existing clearPending('close') logic in place but ensured it is invoked only after stash-clearing where appropriate.
src/main/webapp/oscarRx/ViewScript.jsp
src/main/webapp/oscarRx/ViewScript2.jsp
src/main/java/ca/openosp/openo/prescript/pageUtil/RxWriteScript2Action.java
Tighten logging and minor configuration/formatting around prescriptions.
  • Simplified RxPrescriptionData special-instructions logging to report null/short values and their lengths without SQL escaping side-effects.
  • Made a minor formatting tweak in struts.xml (blank line inside the default package) for readability.
src/main/java/ca/openosp/openo/prescript/data/RxPrescriptionData.java
src/main/webapp/WEB-INF/classes/struts.xml

Assessment against linked issues

Issue Objective Addressed Explanation
#2237 Implement per‑patient RxSessionBean storage (demographicNo‑keyed) across the Rx workflow so that opening Medications/Allergies for multiple patients in different tabs no longer overwrites staged prescriptions or mixes sessions.
#2237 Fix the NullPointerException in RxWriteScript2Action.updateDrug() by safely handling invalid randomId values and missing prescriptions in the stash.
#2237 Correct the provider comparison bug in RxShowAllergy2Action so it no longer relies on incorrect String inequality semantics when dealing with provider/patient context.

Possibly linked issues

  • #N/A: They address the same bug: shared RxSessionBean causing lost staged prescriptions and NPEs with multiple patient tabs.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 3, 2026

📝 Walkthrough

Walkthrough

This pull request refactors the prescription system's session management to support multi-patient/multi-tab scenarios by implementing per-demographic-number session keys instead of a single shared session attribute. A new servlet filter (RxSessionFilter) and utility methods in RxSessionBean manage dual-key storage for backward compatibility. Client-side changes propagate the demographicNo parameter through AJAX calls and forms via a new JavaScript interceptor. Several Java actions are updated to use the new session utilities, and multiple JSP pages are modified to pass and use demographicNo context. Additional defensive checks handle null prescriptions and validate parameters.

Changes

Cohort / File(s) Summary
Session Management Infrastructure
RxSessionBean.java, RxSessionFilter.java, web.xml
Added per-demographic session key utilities to RxSessionBean (getFromSession, saveToSession, getSessionKey) with fallback to legacy key for migration. Introduced new servlet filter RxSessionFilter to intercept requests, determine demographicNo, and populate legacy session key from per-patient bean. Registered filter in web.xml for /oscarRx/*, /CaseManagementView.do, and /messenger/generatePreviewPDF.jsp.
Java Action Classes
CaseManagementView2Action.java, RxChoosePatient2Action.java, RxShowAllergy2Action.java
Refactored bean retrieval to use RxSessionBean.getFromSession(request, demographicNoInt) and persistence via RxSessionBean.saveToSession(request, bean) instead of direct session attribute manipulation, enabling per-demographic bean storage.
Prescription Handling
RxPrescriptionData.java, RxWriteScript2Action.java
Simplified special field validation in RxPrescriptionData by removing escapeSql-based checks and using raw getSpecial() value. Updated RxWriteScript2Action.setDemographicNo signature from int to String with safe parsing, and added null-check with HTTP 400 error response for missing prescriptions in updateQty path.
Client-Side Session Support
rxSessionInterceptor.js, SearchDrug3.jsp, ViewScript.jsp, ViewScript2.jsp
Created new rxSessionInterceptor.js to auto-inject demographicNo parameter into AJAX requests (Prototype.js and jQuery) and form submissions. Updated JSP files to expose currentDemographicNo global variable, pass demographicNo in iframe URLs and form fields, and include the interceptor script.
Patient Data Retrieval
ListDrugs.jsp, generatePreviewPDF.jsp
Refactored patient data lookup to prefer demographicNo request parameter over session Patient, with fallback to session attribute. Updated to use RxSessionBean.getFromSession and saveToSession for per-demographic context management.
Configuration
struts.xml
Minor whitespace formatting change (blank line insertion).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • yingbull

Poem

🐰 Hops through sessions, patient by patient,
No more tangled tabs, the fix is quite latent,
Each demographic gets its own little space,
AJAX now knows its rightful place,
Filters and beans in harmony dance,
Multi-tab chaos? Not a chance! 🌿

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: fixing missing staged medications when using save and print with multiple patient Rx pages open, addressing a legacy bug.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch bug/missing-meds-when-saving

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello @LiamStanziani, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the prescription management module by introducing a comprehensive per-patient session handling mechanism. This architectural improvement addresses data integrity concerns and improves the user experience by allowing the simultaneous management of prescriptions for multiple patients across different browser tabs. The solution integrates both server-side session filtering and client-side JavaScript interception to ensure accurate and consistent data handling.

Highlights

  • Multi-Patient Prescription Tab Support: Implemented a robust per-patient session management system for prescription data, enabling users to open and manage prescriptions for multiple patients in separate browser tabs without data cross-contamination.
  • New RxSessionFilter for Context Management: Introduced a new servlet filter, RxSessionFilter, which dynamically manages the RxSessionBean in the HTTP session. This ensures that the correct patient's prescription data is always active for relevant requests, providing seamless context switching.
  • Enhanced RxSessionBean Functionality: Added static helper methods (getFromSession, saveToSession) to RxSessionBean for consistent and safe retrieval and storage of patient-specific prescription data. This includes logic for backward compatibility, migrating legacy session beans to the new per-patient key.
  • Client-Side AJAX and Form Interception: Developed a new JavaScript file, rxSessionInterceptor.js, which automatically injects the patient's demographic number into Prototype.js and jQuery AJAX requests, as well as relevant form submissions. This client-side change works in conjunction with the server-side filter to maintain patient context.
  • Improved Prescription Saving Robustness: Added a null check when retrieving prescriptions from the stash in RxWriteScript2Action.java. This prevents potential errors and provides better feedback to the user if a prescription is unexpectedly missing during the saving process.
Changelog
  • src/main/java/ca/openosp/openo/casemgmt/web/CaseManagementView2Action.java
    • Updated RxSessionBean initialization to utilize new per-patient session management methods (getFromSession, saveToSession).
  • src/main/java/ca/openosp/openo/prescript/data/RxPrescriptionData.java
    • Removed unused StringEscapeUtils import.
    • Refactored logging for 'drug special' values, removing SQL escaping and improving clarity.
  • src/main/java/ca/openosp/openo/prescript/pageUtil/RxChoosePatient2Action.java
    • Modified RxSessionBean setup to leverage per-patient session keys for multi-patient tab support.
  • src/main/java/ca/openosp/openo/prescript/pageUtil/RxSessionBean.java
    • Added static methods getSessionKey, getFromSession, and saveToSession for per-patient session management.
    • Implemented logic within getFromSession for migrating legacy session beans to the new per-patient key.
    • Added HttpServletRequest and HttpSession imports.
  • src/main/java/ca/openosp/openo/prescript/pageUtil/RxSessionFilter.java
    • Added new file: Implemented a servlet filter to manage RxSessionBean context per request, supporting multi-patient tabs.
  • src/main/java/ca/openosp/openo/prescript/pageUtil/RxShowAllergy2Action.java
    • Refactored RxSessionBean handling to utilize the new per-patient session methods, simplifying bean retrieval and creation logic.
  • src/main/java/ca/openosp/openo/prescript/pageUtil/RxWriteScript2Action.java
    • Added a null check for RxPrescriptionData.Prescription retrieval from the stash to prevent NullPointerException and provide client-side error feedback.
    • Updated setDemographicNo method signature to accept String and included robust parsing logic with error handling.
  • src/main/webapp/WEB-INF/struts.xml
    • Minor formatting change (added a blank line).
  • src/main/webapp/WEB-INF/web.xml
    • Registered the new RxSessionFilter and mapped it to relevant URL patterns (/oscarRx/*, /CaseManagementView.do, /messenger/generatePreviewPDF.jsp) to ensure proper application.
  • src/main/webapp/messenger/generatePreviewPDF.jsp
    • Updated RxSessionBean and patient data setup to use the new per-patient session methods for consistent context.
  • src/main/webapp/oscarRx/ListDrugs.jsp
    • Modified patient data retrieval logic to prioritize demographicNo from request parameters, falling back to the RxSessionBean and then legacy session attributes, to support multi-tab patient views.
  • src/main/webapp/oscarRx/SearchDrug3.jsp
    • Integrated rxSessionInterceptor.js for client-side demographic number injection into AJAX calls and forms.
    • Updated form input property attribute to name for demographicNo to ensure correct form submission.
    • Introduced clearStashOnLightwindowClose flag and handleLightwindowClose function to manage clearing the prescription stash when the lightwindow closes, particularly after 'Save & Print'.
    • Appended demographicNo to ViewScript2.jsp URLs for maintaining patient context.
  • src/main/webapp/oscarRx/ViewScript.jsp
    • Integrated rxSessionInterceptor.js for client-side demographic number injection.
    • Added demographicNo to the Preview.jsp iframe source and the clearPending form.
    • Modified the 'Back to Oscar' button's onClick event to call resetStash() before closing.
  • src/main/webapp/oscarRx/ViewScript2.jsp
    • Integrated rxSessionInterceptor.js for client-side demographic number injection.
    • Introduced resetStashAndClose() function to clear both the stash and re-Rx drug list, then close the window.
    • Added demographicNo to the Preview2.jsp iframe source and the clearPending form.
    • Modified the 'Back to Oscar' button's onClick event to use resetStashAndClose().
  • src/main/webapp/oscarRx/js/rxSessionInterceptor.js
    • Added new file: JavaScript utility to automatically add demographicNo to Prototype.js and jQuery AJAX requests, as well as forms, for Rx-related pages to ensure patient context is always passed.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a significant and well-designed enhancement for handling prescription sessions on a per-patient basis, which is crucial for supporting multi-tab workflows. The use of a servlet filter, session bean helpers with backward compatibility, and a client-side AJAX interceptor is a solid approach. My review has identified a recurring high-severity issue: several new code paths parse request parameters into integers without proper error handling for NumberFormatException. This could lead to unhandled exceptions and server errors. I have provided specific comments and code suggestions to address this by adding robust try-catch blocks.

Comment thread src/main/java/ca/openosp/openo/casemgmt/web/CaseManagementView2Action.java Outdated
Comment thread src/main/java/ca/openosp/openo/prescript/pageUtil/RxChoosePatient2Action.java Outdated
Comment thread src/main/java/ca/openosp/openo/prescript/pageUtil/RxShowAllergy2Action.java Outdated
Comment thread src/main/java/ca/openosp/openo/prescript/pageUtil/RxWriteScript2Action.java Outdated
Comment thread src/main/webapp/messenger/generatePreviewPDF.jsp Outdated
@LiamStanziani
Copy link
Copy Markdown
Collaborator Author

@copilot review

Copy link
Copy Markdown

Copilot AI commented Feb 3, 2026

@LiamStanziani I've opened a new pull request, #2262, to work on those changes. Once the pull request is ready, I'll request review from you.

@LiamStanziani
Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 3, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 15

🤖 Fix all issues with AI agents
In `@src/main/java/ca/openosp/openo/casemgmt/web/CaseManagementView2Action.java`:
- Around line 458-467: The code currently calls Integer.parseInt(demoNo) without
handling NumberFormatException; wrap the parse in a safe guard (e.g., check
demoNo for null/empty and digits or use a try/catch) inside the method in
CaseManagementView2Action before calling
RxSessionBean.getFromSession/saveToSession; on parse failure, either use a
sensible default demographicNo (e.g., 0) or skip creating/saving the
RxSessionBean and log a warning with the invalid demoNo so the request does not
throw a 500. Ensure you still call RxSessionBean.setProviderNo and save only
when a valid demographicNo was obtained.

In `@src/main/java/ca/openosp/openo/prescript/data/RxPrescriptionData.java`:
- Around line 1650-1654: The code calls getSpecial() which may log raw PHI;
instead read the underlying field directly in RxPrescriptionData (avoid invoking
getSpecial()) or add a non-logging accessor (e.g., getSpecialRaw()) and use that
to compute length for the warning; ensure the log message only includes the
length (no content) and if you must log any sanitized value use Encode.forJava()
to prevent log injection.

In
`@src/main/java/ca/openosp/openo/prescript/pageUtil/RxChoosePatient2Action.java`:
- Around line 85-96: The code calls Integer.parseInt(this.getDemographicNo())
without validating the input, which will throw if getDemographicNo() is null or
not numeric; update the method in RxChoosePatient2Action to first check that
this.getDemographicNo() is non-null and matches a numeric pattern (or try
parsing inside a try/catch), and if invalid return the appropriate error view
("error.html" or "Logout"); then only call Integer.parseInt and proceed to use
RxSessionBean.getFromSession(request, demographicNoInt) and
RxSessionBean.saveToSession(request, bean) when the demographicNo is valid.

In `@src/main/java/ca/openosp/openo/prescript/pageUtil/RxSessionBean.java`:
- Around line 47-112: The public session helper methods (getSessionKey,
getFromSession(HttpSession,int), getFromSession(HttpServletRequest,int),
saveToSession(HttpSession,RxSessionBean),
saveToSession(HttpServletRequest,RxSessionBean)) need complete JavaDoc: add
explicit `@param` entries specifying types (e.g., "@param demographicNo int",
"@param session HttpSession", "@param request HttpServletRequest", "@param bean
RxSessionBean"), add precise `@return` tags (e.g., "@return RxSessionBean or null"
or "@return String" for getSessionKey), add `@throws` tags for any
unchecked/checked exceptions the methods may surface (or explicitly state none),
and add `@since` tags populated from git history for each public method; update
the JavaDoc blocks above each referenced method accordingly.

In `@src/main/java/ca/openosp/openo/prescript/pageUtil/RxSessionFilter.java`:
- Around line 36-95: Add comprehensive JavaDoc to the public class
RxSessionFilter and its public methods init(FilterConfig),
doFilter(ServletRequest, ServletResponse, FilterChain), and destroy(): document
each `@param` with exact types (e.g., `@param` filterConfig
javax.servlet.FilterConfig), include `@throws` tags for
ServletException/IOException where applicable, add `@since` tags using the
commit/date when the class was introduced, and include a brief description of
behavior and return type (where applicable — void) for each method; ensure the
class-level JavaDoc also lists the purpose and the LEGACY_KEY behavior
referenced in doFilter.
- Around line 81-83: The logger.warn in RxSessionFilter currently logs
demographicNo (PHI) and the raw request URI; remove demographicNo from the log
message and sanitize the URI before logging. Update the logging call in
RxSessionFilter (the logger.warn that references demographicNo and
request.getRequestURI()) to omit demographicNo entirely and pass the request URI
through a safe sanitizer such as Encode.forJava() (or your project's approved
sanitizer) before including it in the log message to prevent log injection and
PHI exposure. Ensure only non-PHI, sanitized values are logged and adjust the
log text accordingly.

In `@src/main/java/ca/openosp/openo/prescript/pageUtil/RxShowAllergy2Action.java`:
- Around line 175-190: The code in RxShowAllergy2Action currently uses
Integer.parseInt(demo_no) which can throw NumberFormatException; update the
handler to validate demo_no (e.g., check null/empty and digits or use try/catch
around Integer.parseInt) and on invalid input set the response status to
SC_BAD_REQUEST (or return "failure") instead of allowing a 500; preserve the
existing RxSessionBean creation and RxSessionBean.saveToSession logic when the
parse succeeds, and ensure any NumberFormatException branch skips bean creation
and exits early with the bad-request response.

In `@src/main/java/ca/openosp/openo/prescript/pageUtil/RxWriteScript2Action.java`:
- Around line 813-821: The logger.error call in RxWriteScript2Action logs the
user-supplied randomId directly; sanitize it using Encode.forJava(randomId) and
switch to parameterized logging (e.g., logger.error("Prescription not found in
stash for randomId: {}", Encode.forJava(randomId))) so the input is encoded and
not concatenated into the message; update the logger invocation around the
null-check for rx and add the necessary import for Encode.
- Around line 1563-1570: Add comprehensive JavaDoc to the public setter
setDemographicNo in class RxWriteScript2Action describing its purpose, include a
typed `@param` tag (e.g., `@param` RHS String - numeric string to parse into an
int), a `@since` tag with the appropriate git-history date, and document behavior
on invalid input (note that NumberFormatException is caught and the default
remains 0) — include an `@throws` tag only if the method is changed to propagate
exceptions; otherwise explicitly state in the JavaDoc that invalid numeric input
is swallowed and no exception is thrown.

In `@src/main/webapp/oscarRx/js/rxSessionInterceptor.js`:
- Around line 21-38: The demographic injection functions must handle FormData
and URLSearchParams explicitly: in addDemographicNo (and correspondingly
hasDemographicNo if needed) detect instances of FormData and URLSearchParams
(e.g., params instanceof FormData / params instanceof URLSearchParams) and use
their APIs instead of treating them as plain objects—call
formData.append('demographicNo', demoNo) for FormData and
urlSearchParams.set('demographicNo', demoNo) for URLSearchParams; preserve
existing behavior for strings (append as query param) and plain objects (assign
params.demographicNo = demoNo), and ensure hasDemographicNo checks FormData.has
and URLSearchParams.has or inspects string/query properly so injection isn't
skipped.

In `@src/main/webapp/oscarRx/SearchDrug3.jsp`:
- Around line 238-243: The demographicNo is being output unencoded in
JavaScript, HTML attributes, and URI contexts; add the import
org.owasp.encoder.Encode at the top and replace direct uses of
rxSessionBean.getDemographicNo() with context-appropriate encoding: wrap it with
Encode.forJavaScript(...) when assigning the JavaScript variable
currentDemographicNo, use Encode.forHtmlAttribute(...) where demographicNo is
inserted into hidden input value attributes, and use Encode.forUriComponent(...)
where demographicNo is concatenated into query parameter strings (search for
currentDemographicNo, the hidden input value usages, and the methods/builders
that append demographicNo to query URIs to update each).

In `@src/main/webapp/oscarRx/ViewScript.jsp`:
- Around line 322-325: The RxClearPendingForm POST is missing the CSRF token;
update the form named "RxClearPendingForm" (action "/oscarRx/clearPending.do")
to include a hidden input using the Spring CSRF parameters: add an input with
name="${_csrf.parameterName}" and value="${_csrf.token}" alongside the existing
hidden fields (e.g., near the demographicNo input) so the form submits the CSRF
token.
- Around line 171-176: Import the OWASP encoder by adding <%@ page
import="org.owasp.encoder.Encode" %> and then apply context-appropriate encoding
to demographicNo: replace the unencoded embed that sets the JavaScript variable
currentDemographicNo (variable currentDemographicNo in ViewScript.jsp) with
Encode.forJavaScript(bean.getDemographicNo()), encode the URL parameter usage
(the code that builds the src or query param around rxSessionInterceptor.js or
other URL at line ~317) with Encode.forUriComponent(bean.getDemographicNo()),
and encode any HTML attribute usage (the attribute at ~324) with
Encode.forHtmlAttribute(bean.getDemographicNo()); finally, add the missing CSRF
hidden input to the POST form (the form around line ~322) using <input
type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> so the form
includes the CSRF token.

In `@src/main/webapp/oscarRx/ViewScript2.jsp`:
- Around line 675-678: The RxClearPendingForm POST form (form name
"RxClearPendingForm", action "/oscarRx/clearPending.do") is missing a CSRF
token; add a hidden input using the application's CSRF attributes (e.g. <input
type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> or the
project's equivalent) inside the form (near the other hidden inputs like
"action" and "demographicNo") so the server can validate the token on
submission.
- Around line 238-243: currentDemographicNo is being output unencoded in
multiple contexts causing XSS/CSRF issues; replace all direct uses of
bean.getDemographicNo() with context-appropriate OWASP encoders: wrap the value
in Encode.forJavaScript() when assigning the JavaScript variable
currentDemographicNo (the script block that sets var currentDemographicNo), use
Encode.forUriComponent() when appending demographicNo into URLs (the places
building query params), and use Encode.forHtmlAttribute() when inserting
demographicNo into HTML attributes; update the other occurrences of
demographicNo (the remaining usages in this JSP) similarly to their contexts,
and add a hidden CSRF token input to the POST form (include the server-side CSRF
token variable provided by the app framework) so the form submits the CSRF
token.
🧹 Nitpick comments (4)
src/main/webapp/oscarRx/js/rxSessionInterceptor.js (1)

41-68: Use camelCase for local aliases.
Rename OriginalRequest/OriginalUpdater to camelCase to match JS naming conventions.

♻️ Suggested refactor
-        var OriginalRequest = Ajax.Request;
+        var originalRequest = Ajax.Request;
         Ajax.Request = function(url, options) {
@@
-            return new OriginalRequest(url, options);
+            return new originalRequest(url, options);
         };
-        Ajax.Request.prototype = OriginalRequest.prototype;
+        Ajax.Request.prototype = originalRequest.prototype;
@@
-        var OriginalUpdater = Ajax.Updater;
+        var originalUpdater = Ajax.Updater;
         Ajax.Updater = function(container, url, options) {
@@
-            return new OriginalUpdater(container, url, options);
+            return new originalUpdater(container, url, options);
         };
-        Ajax.Updater.prototype = OriginalUpdater.prototype;
+        Ajax.Updater.prototype = originalUpdater.prototype;
As per coding guidelines: **/*.{java,js,ts,tsx}: Use camelCase for variable and method names (e.g., `ticklerManager`, `isPatientActive()`, `getLastUpdateDate()`).
src/main/webapp/oscarRx/ListDrugs.jsp (1)

69-95: Move demographicNo parsing out of JSP scriptlets.
Consider resolving the demographic context in a controller and passing it via request attributes/JSTL to keep the view logic minimal.

As per coding guidelines: JSP views should use JSTL tags and avoid Java scriptlets - use request.getAttribute() for passing data.

src/main/webapp/messenger/generatePreviewPDF.jsp (2)

410-423: Rename Rxbean to camelCase rxBean.
Aligns with Java naming conventions.

♻️ Suggested refactor
-                                            RxSessionBean Rxbean = RxSessionBean.getFromSession(request.getSession(), demoNoInt);
+                                            RxSessionBean rxBean = RxSessionBean.getFromSession(request.getSession(), demoNoInt);
 
-                                            if (Rxbean == null) {
-                                                Rxbean = new RxSessionBean();
+                                            if (rxBean == null) {
+                                                rxBean = new RxSessionBean();
                                             }
@@
-                                            Rxbean.setProviderNo((String) request.getSession().getAttribute("user"));
-                                            Rxbean.setDemographicNo(demoNoInt);
+                                            rxBean.setProviderNo((String) request.getSession().getAttribute("user"));
+                                            rxBean.setDemographicNo(demoNoInt);
@@
-                                            RxSessionBean.saveToSession(request.getSession(), Rxbean);
+                                            RxSessionBean.saveToSession(request.getSession(), rxBean);
As per coding guidelines: **/*.{java,js,ts,tsx}: Use camelCase for variable and method names (e.g., `ticklerManager`, `isPatientActive()`, `getLastUpdateDate()`).

410-423: Move Rx session setup out of JSP scriptlets.
Prefer resolving RxSessionBean in a controller and passing it via request attributes/JSTL.

As per coding guidelines: JSP views should use JSTL tags and avoid Java scriptlets - use request.getAttribute() for passing data.

Comment thread src/main/java/ca/openosp/openo/casemgmt/web/CaseManagementView2Action.java Outdated
Comment thread src/main/java/ca/openosp/openo/prescript/pageUtil/RxChoosePatient2Action.java Outdated
Comment thread src/main/webapp/oscarRx/SearchDrug3.jsp Outdated
Comment thread src/main/webapp/oscarRx/ViewScript.jsp
Comment thread src/main/webapp/oscarRx/ViewScript.jsp
Comment thread src/main/webapp/oscarRx/ViewScript2.jsp
Comment thread src/main/webapp/oscarRx/ViewScript2.jsp
@LiamStanziani LiamStanziani marked this pull request as ready for review February 3, 2026 16:03
@qodo-code-review
Copy link
Copy Markdown

qodo-code-review bot commented Feb 3, 2026

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
Authorization bypass

Description: The filter trusts the client-supplied demographicNo request parameter to select/swap the
active RxSessionBean without verifying the logged-in user's authorization for that
patient, which could enable an attacker to force context-switching to another patient's Rx
session and potentially access/modify another patient's prescription workflow if
downstream code relies on this bean for patient context.
RxSessionFilter.java [57-89]

Referred Code
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
        throws IOException, ServletException {
    HttpServletRequest request = (HttpServletRequest) req;
    HttpSession session = request.getSession(false);

    if (session != null) {
        int demographicNo = parseDemographicNo(request.getParameter("demographicNo"));
        boolean usedFallback = false;

        if (demographicNo <= 0) {
            RxSessionBean currentBean = (RxSessionBean) session.getAttribute(LEGACY_KEY);
            if (currentBean != null) {
                demographicNo = currentBean.getDemographicNo();
                usedFallback = true;
            }
        }

        if (demographicNo > 0) {
            RxSessionBean perPatientBean = (RxSessionBean) session.getAttribute(
                    RxSessionBean.getSessionKey(demographicNo));


 ... (clipped 12 lines)
SQL injection

Description: The PR removes SQL escaping of special (previously
StringEscapeUtils.escapeSql(this.getSpecial())) and now uses the raw this.special, which
could reintroduce SQL injection risk if any downstream persistence/query code interpolates
this field into SQL rather than using parameterized statements.
RxPrescriptionData.java [1650-1657]

Referred Code
if (this.special == null || this.special.length() < 6) {
    logger.warn("drug special appears to be null or empty (length={})",
            this.special == null ? 0 : this.special.length());
}

DrugDao dao = SpringUtils.getBean(DrugDao.class);
Drug drug = new Drug();
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

🔴
Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status:
Non-descriptive parameter: The new setter setDemographicNo(String RHS) uses the identifier RHS, which is not
self-documenting and obscures the meaning of the incoming demographic number value.

Referred Code
/**
 * Sets the demographic number from a String value, as provided by Struts2
 * parameter binding from the {@code demographicNo} request parameter.
 *
 * @param RHS String the demographic number to parse; ignored if null, empty, or non-numeric
 * @since 2026-01-30
 */
public void setDemographicNo(String RHS) {
    if (RHS != null && !RHS.isEmpty()) {
        try {
            this.demographicNo = Integer.parseInt(RHS);
        } catch (NumberFormatException e) {
            // Keep default value (0) if parse fails
        }
    }
}

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status:
Swallowed parse error: The new setDemographicNo(String RHS) silently ignores non-numeric input without returning
an error or logging, which can lead to confusing downstream behavior with the default
demographicNo value.

Referred Code
public void setDemographicNo(String RHS) {
    if (RHS != null && !RHS.isEmpty()) {
        try {
            this.demographicNo = Integer.parseInt(RHS);
        } catch (NumberFormatException e) {
            // Keep default value (0) if parse fails
        }
    }

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status:
Limited audit coverage: The new per-patient Rx session switching and stash-related behaviors do not add an
auditable record tying patient/session swaps or prescription-stash operations to a user
and outcome, making reconstruction of Rx context changes difficult.

Referred Code
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
        throws IOException, ServletException {
    HttpServletRequest request = (HttpServletRequest) req;
    HttpSession session = request.getSession(false);

    if (session != null) {
        int demographicNo = parseDemographicNo(request.getParameter("demographicNo"));
        boolean usedFallback = false;

        if (demographicNo <= 0) {
            RxSessionBean currentBean = (RxSessionBean) session.getAttribute(LEGACY_KEY);
            if (currentBean != null) {
                demographicNo = currentBean.getDemographicNo();
                usedFallback = true;
            }
        }

        if (demographicNo > 0) {
            RxSessionBean perPatientBean = (RxSessionBean) session.getAttribute(
                    RxSessionBean.getSessionKey(demographicNo));


 ... (clipped 12 lines)

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status:
Potentially sensitive identifier: New error logs include request-supplied identifiers like randomId (even though encoded),
and without knowing local policy on logging patient/Rx workflow identifiers it is unclear
if this meets the project's PII/PHI logging restrictions.

Referred Code
    logger.error("Invalid randomId parameter: {}", Encode.forJava(randomId));
    response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
    ObjectNode errorResponse = objectMapper.createObjectNode();
    errorResponse.put("error", "Invalid prescription identifier.");
    response.getOutputStream().write(errorResponse.toString().getBytes());
    return null;
}
RxPrescriptionData.Prescription rx = bean.getStashItem2(randomIdInt);
if (rx == null) {
    logger.error("Prescription not found in stash for randomId: {}. " +
                 "Session may have been reset or prescription was not properly staged.",
                 Encode.forJava(randomId));
    response.setStatus(HttpServletResponse.SC_BAD_REQUEST);

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status:
Trust boundary unclear: The filter now trusts the client-provided demographicNo to select and swap the per-patient
RxSessionBean into the legacy key, and the diff does not show any authorization/ownership
validation that the request is permitted to operate on that patient context.

Referred Code
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
        throws IOException, ServletException {
    HttpServletRequest request = (HttpServletRequest) req;
    HttpSession session = request.getSession(false);

    if (session != null) {
        int demographicNo = parseDemographicNo(request.getParameter("demographicNo"));
        boolean usedFallback = false;

        if (demographicNo <= 0) {
            RxSessionBean currentBean = (RxSessionBean) session.getAttribute(LEGACY_KEY);
            if (currentBean != null) {
                demographicNo = currentBean.getDemographicNo();
                usedFallback = true;
            }
        }

        if (demographicNo > 0) {
            RxSessionBean perPatientBean = (RxSessionBean) session.getAttribute(
                    RxSessionBean.getSessionKey(demographicNo));


 ... (clipped 9 lines)

Learn more about managing compliance generic rules or creating your own custom rules

  • Update
Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

Copy link
Copy Markdown

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 2 issues, and left some high level feedback:

  • In RxWriteScript2Action.updateDrug, when returning the JSON error responses you should explicitly set the response Content-Type (e.g., application/json with UTF‑8) and use a consistent charset when writing bytes instead of relying on defaults.
  • The heuristics in rxSessionInterceptor.js for adding demographicNo (string checks for 'Rx' in form action and only checking for 'demographicNo=' in raw strings) are quite broad and could affect unrelated forms or miss encoded params; consider tightening the action matching and using proper querystring parsing instead of substring checks.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In RxWriteScript2Action.updateDrug, when returning the JSON error responses you should explicitly set the response Content-Type (e.g., application/json with UTF‑8) and use a consistent charset when writing bytes instead of relying on defaults.
- The heuristics in rxSessionInterceptor.js for adding demographicNo (string checks for 'Rx' in form action and only checking for 'demographicNo=' in raw strings) are quite broad and could affect unrelated forms or miss encoded params; consider tightening the action matching and using proper querystring parsing instead of substring checks.

## Individual Comments

### Comment 1
<location> `src/main/webapp/oscarRx/ViewScript.jsp:384-387` </location>
<code_context>
                                             <td><span><input type=button
                                                              value="<fmt:setBundle basename="oscarResources"/><fmt:message key="ViewScript.msgBackToOscar"/>"
                                                              class="ControlPushButton" style="width: 200px"
-                                                             onClick="javascript:clearPending('close');"/></span></td>
+                                                             onClick="resetStash();javascript:clearPending('close');"/></span></td>
                                         </tr>

</code_context>

<issue_to_address>
**issue (bug_risk):** Calling resetStash() here will throw a JS error because it is not defined on this page.

On ViewScript2.jsp `resetStash()` is defined locally, but on ViewScript.jsp it isn’t present and there’s no script import that provides it. As written, clicking “Back to Oscar” will throw `ReferenceError: resetStash is not defined`. To keep the stash-clearing behavior, either define `resetStash` on this page, move it into a shared JS file, or reuse an existing function that already clears the stash.
</issue_to_address>

### Comment 2
<location> `src/main/java/ca/openosp/openo/prescript/pageUtil/RxWriteScript2Action.java:811-819` </location>
<code_context>
                 String randomId = request.getParameter("randomId");
-                RxPrescriptionData.Prescription rx = bean.getStashItem2(Integer.parseInt(randomId));
-                // get prescript from randomId
+                int randomIdInt;
+                try {
+                    randomIdInt = Integer.parseInt(randomId);
+                } catch (NumberFormatException e) {
+                    logger.error("Invalid randomId parameter: {}", Encode.forJava(randomId));
+                    response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+                    ObjectNode errorResponse = objectMapper.createObjectNode();
+                    errorResponse.put("error", "Invalid prescription identifier.");
+                    response.getOutputStream().write(errorResponse.toString().getBytes());
+                    return null;
+                }
</code_context>

<issue_to_address>
**suggestion (bug_risk):** Error JSON responses should set content type and charset to avoid client-side parsing issues.

In the invalid `randomId` (and similar `rx == null`) branches you write a JSON error body to the `ServletOutputStream` without setting a `Content-Type`. This can prevent some clients or intermediaries from treating it as JSON and may introduce charset issues. Please set `response.setContentType("application/json;charset=UTF-8");` before writing the body and encode with `getBytes(StandardCharsets.UTF_8)` (or use a writer).

Suggested implementation:

```java
                    logger.error("Invalid randomId parameter: {}", Encode.forJava(randomId));
                    response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                    ObjectNode errorResponse = objectMapper.createObjectNode();
                    errorResponse.put("error", "Invalid prescription identifier.");
                    response.setContentType("application/json;charset=UTF-8");
                    response.getOutputStream().write(errorResponse.toString().getBytes(StandardCharsets.UTF_8));
                    return null;

```

```java
                    logger.error("Prescription not found in stash for randomId: {}. " +
                                 "Session may have been reset or prescription was not properly staged.",
                                 Encode.forJava(randomId));
                    response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                    ObjectNode errorResponse = objectMapper.createObjectNode();
                    errorResponse.put("error", "Prescription not found. Please refresh and try again.");
                    response.setContentType("application/json;charset=UTF-8");
                    response.getOutputStream().write(errorResponse.toString().getBytes(StandardCharsets.UTF_8));
                    return null;

```

1. Ensure `java.nio.charset.StandardCharsets` is imported at the top of `RxWriteScript2Action.java`, e.g.:
   `import java.nio.charset.StandardCharsets;`
2. If there are other JSON error branches in this class that write directly to the response without setting a content type or charset, apply the same `setContentType("application/json;charset=UTF-8")` and `getBytes(StandardCharsets.UTF_8)` pattern there for consistency.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread src/main/webapp/oscarRx/ViewScript.jsp
Comment thread src/main/java/ca/openosp/openo/prescript/pageUtil/RxWriteScript2Action.java Outdated
@qodo-code-review
Copy link
Copy Markdown

qodo-code-review bot commented Feb 3, 2026

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Prevent using stale session data
Suggestion Impact:The commit adds logic to remove the legacy session attribute when demographicNo is explicitly provided but no per-patient bean exists, preventing cross-patient leakage from a stale legacy bean. The conditional structure differs from the suggestion but implements the core safeguard.

code diff:

@@ -77,7 +77,11 @@
                         RxSessionBean.getSessionKey(demographicNo));
                 if (perPatientBean != null) {
                     session.setAttribute(LEGACY_KEY, perPatientBean);
-                } else if (usedFallback) {
+                } else if (!usedFallback) {
+                    // demographicNo was explicitly provided but no per-patient bean exists.
+                    // Clear the legacy key to prevent cross-patient leakage from a stale bean.
+                    session.removeAttribute(LEGACY_KEY);
+                } else {

In RxSessionFilter, if a per-patient bean is not found for the requested
demographicNo, remove the legacy session bean to prevent using stale data from
another patient.

src/main/java/ca/openosp/openo/prescript/pageUtil/RxSessionFilter.java [75-85]

 if (demographicNo > 0) {
     RxSessionBean perPatientBean = (RxSessionBean) session.getAttribute(
             RxSessionBean.getSessionKey(demographicNo));
     if (perPatientBean != null) {
         session.setAttribute(LEGACY_KEY, perPatientBean);
-    } else if (usedFallback) {
-        logger.warn("RxSessionFilter: No demographicNo param and no per-patient bean " +
-                "found for {}. Using legacy bean as-is.",
-                Encode.forJava(request.getRequestURI()));
+    } else {
+        // No per-patient bean found for the requested demographic.
+        // Remove the legacy bean to prevent using a bean for the wrong patient.
+        session.removeAttribute(LEGACY_KEY);
+        if (usedFallback) {
+            logger.warn("RxSessionFilter: No demographicNo param and no per-patient bean " +
+                    "found for {}. Using legacy bean as-is.",
+                    Encode.forJava(request.getRequestURI()));
+        }
     }
 }

[Suggestion processed]

Suggestion importance[1-10]: 8

__

Why: This suggestion correctly identifies a data cross-contamination bug in the new RxSessionFilter logic, where a stale session bean could be used for the wrong patient. Applying this fix is critical for the correctness of the multi-tab feature introduced in this PR.

Medium
General
Improve demographicNo existence check

In hasDemographicNo, use the .has() method to correctly check for the existence
of the demographicNo parameter in URLSearchParams and FormData objects.

src/main/webapp/oscarRx/js/rxSessionInterceptor.js [21-26]

 function hasDemographicNo(params) {
     if (!params) return false;
-    if (typeof params === 'string') return params.indexOf('demographicNo=') !== -1;
-    if (typeof params === 'object') return 'demographicNo' in params;
+    if (typeof params === 'string') {
+        return params.indexOf('demographicNo=') !== -1;
+    }
+    if (params instanceof URLSearchParams || params instanceof FormData) {
+        return params.has('demographicNo');
+    }
+    if (typeof params === 'object') {
+        return 'demographicNo' in params;
+    }
     return false;
 }
  • Apply / Chat
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies a bug in the new JavaScript interceptor where checking for the existence of demographicNo would fail for FormData and URLSearchParams objects. The fix is important for the correct functioning of the interceptor.

Medium
Enforce UTF-8 on JSON output
Suggestion Impact:The commit updated JSON error responses to encode bytes using StandardCharsets.UTF_8 and added an explicit UTF-8 JSON content type (application/json;charset=UTF-8), improving charset handling for the response output.

code diff:

+import java.nio.charset.StandardCharsets;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -814,9 +815,10 @@
                 } catch (NumberFormatException e) {
                     logger.error("Invalid randomId parameter: {}", Encode.forJava(randomId));
                     response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+                    response.setContentType("application/json;charset=UTF-8");
                     ObjectNode errorResponse = objectMapper.createObjectNode();
                     errorResponse.put("error", "Invalid prescription identifier.");
-                    response.getOutputStream().write(errorResponse.toString().getBytes());
+                    response.getOutputStream().write(errorResponse.toString().getBytes(StandardCharsets.UTF_8));
                     return null;
                 }
                 RxPrescriptionData.Prescription rx = bean.getStashItem2(randomIdInt);
@@ -825,9 +827,10 @@
                                  "Session may have been reset or prescription was not properly staged.",
                                  Encode.forJava(randomId));
                     response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+                    response.setContentType("application/json;charset=UTF-8");
                     ObjectNode errorResponse = objectMapper.createObjectNode();
                     errorResponse.put("error", "Prescription not found. Please refresh and try again.");
-                    response.getOutputStream().write(errorResponse.toString().getBytes());
+                    response.getOutputStream().write(errorResponse.toString().getBytes(StandardCharsets.UTF_8));
                     return null;

Explicitly set the character encoding to UTF-8 for the JSON error response and
use StandardCharsets.UTF_8 when converting the string to bytes.

src/main/java/ca/openosp/openo/prescript/pageUtil/RxWriteScript2Action.java [817-819]

 ObjectNode errorResponse = objectMapper.createObjectNode();
 errorResponse.put("error", "Invalid prescription identifier.");
-response.getOutputStream().write(errorResponse.toString().getBytes());
+response.setCharacterEncoding("UTF-8");
+byte[] jsonBytes = errorResponse.toString().getBytes(StandardCharsets.UTF_8);
+response.getOutputStream().write(jsonBytes);

[Suggestion processed]

Suggestion importance[1-10]: 5

__

Why: This is a valid code quality improvement that makes the application more robust by explicitly setting the character encoding to UTF-8 for JSON responses, preventing potential character display issues.

Low
Log invalid demographic number parameters

In the setDemographicNo method, log a warning when a NumberFormatException
occurs during parsing to improve debugging of malformed requests.

src/main/java/ca/openosp/openo/prescript/pageUtil/RxWriteScript2Action.java [1581-1589]

 public void setDemographicNo(String RHS) {
     if (RHS != null && !RHS.isEmpty()) {
         try {
             this.demographicNo = Integer.parseInt(RHS);
         } catch (NumberFormatException e) {
-            // Keep default value (0) if parse fails
+            // Keep default value (0) if parse fails, but log the issue.
+            logger.warn("Invalid non-numeric demographicNo parameter received: {}", Encode.forJava(RHS), e);
         }
     }
 }
  • Apply / Chat
Suggestion importance[1-10]: 4

__

Why: The suggestion improves code quality by adding logging for silently-handled exceptions, which aids in debugging. It's a good practice but has a moderate impact on the overall functionality.

Low
  • Update

@claude
Copy link
Copy Markdown

claude bot commented Feb 3, 2026

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 15 files

Confidence score: 3/5

  • Multi-tab sessions can submit the wrong patient ID because src/main/webapp/oscarRx/SearchDrug3.jsp still uses the legacy session patient object instead of the per-tab RxSessionBean demographicNo.
  • src/main/java/ca/openosp/openo/prescript/pageUtil/RxSessionFilter.java can leave a stale legacy bean when demographicNo is provided but no per-patient bean exists, risking cross-patient data bleed.
  • These are concrete, user-facing behaviors around patient context and navigation, so there’s some regression risk despite otherwise localized changes.
  • Pay close attention to src/main/webapp/oscarRx/SearchDrug3.jsp, src/main/java/ca/openosp/openo/prescript/pageUtil/RxSessionFilter.java, src/main/webapp/oscarRx/ViewScript.jsp - patient context isolation and client-side navigation errors.
Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="src/main/webapp/oscarRx/SearchDrug3.jsp">

<violation number="1" location="src/main/webapp/oscarRx/SearchDrug3.jsp:796">
P1: This hidden input still uses the session `patient` object instead of the per-tab RxSessionBean demographicNo, so multi-tab sessions can submit the wrong patient ID. Use `demoNo` (from RxSessionBean) to keep requests tied to the correct tab.</violation>
</file>

<file name="src/main/java/ca/openosp/openo/prescript/pageUtil/RxSessionFilter.java">

<violation number="1" location="src/main/java/ca/openosp/openo/prescript/pageUtil/RxSessionFilter.java:78">
P1: When a demographicNo is provided but no per-patient bean exists, the legacy session bean is left untouched, so downstream code can still read a stale bean from a different patient. Clear the legacy key (or set it to null) in this case to avoid cross-patient leakage.</violation>
</file>

<file name="src/main/webapp/oscarRx/ViewScript.jsp">

<violation number="1" location="src/main/webapp/oscarRx/ViewScript.jsp:392">
P2: resetStash() is not defined for this page, so clicking “Back to Oscar” will throw a ReferenceError and can block clearPending from executing. Either define/resetStash for this page or guard the call.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread src/main/webapp/oscarRx/SearchDrug3.jsp Outdated
Comment thread src/main/webapp/oscarRx/ViewScript.jsp Outdated
yingbull pushed a commit to carlos-emr/carlos that referenced this pull request Feb 10, 2026
Implements isolated session management for the prescription (Rx) module
to prevent medication data cross-contamination when providers have
multiple patient tabs open simultaneously.

Core changes:
- Add static helpers to RxSessionBean (getFromSession/saveToSession) for
  per-patient session keying using RxSessionBean_<demographicNo>
- Create RxSessionFilter servlet filter to swap correct per-patient bean
  into legacy "RxSessionBean" session key per request
- Create rxSessionInterceptor.js to inject demographicNo into AJAX calls
  and form submissions for Prototype.js, jQuery, and native forms
- Update all Rx Action classes to use new per-patient session API
- Add demographicNo propagation to ViewScript/ViewScript2 iframes and forms
- Improve error handling in RxWriteScript2Action for missing prescriptions
- Update ListDrugs.jsp to resolve patient from request parameter first

Adapted from openo-beta/open-o PR #2261 by LiamStanziani.
Original commits: 8d3b9b7..be7f6576 (squashed, path/namespace translated)
Upstream PR: openo-beta/Open-O#2261

Changes from upstream:
- File paths translated: ca/openosp/openo/ -> io/github/carlos_emr/carlos/
- Package names translated: ca.openosp.openo. -> io.github.carlos_emr.carlos.
- RxPrescriptionData.java changes already present in CARLOS (skipped)
- struts.xml whitespace-only change skipped
- Adapted to existing CARLOS codebase divergences

https://claude.ai/code/session_01Jg6sucQ6C6PgndyCrCHqs1
yingbull pushed a commit to carlos-emr/carlos that referenced this pull request Feb 25, 2026
…contamination

Port of openo-beta/open-o PR #2261 ("Fix: missing meds when saving - LEGACY BUG")
originally authored by LiamStanziani.

When multiple prescription tabs are open simultaneously for different patients,
a single shared "RxSessionBean" session attribute causes medications to disappear
or mix between patients. This fix introduces per-patient session keys
(RxSessionBean_<demographicNo>) with a servlet filter that swaps the correct bean
into the legacy key per request, maintaining backward compatibility.

Changes:
- RxSessionBean: Add static getFromSession/saveToSession methods with per-patient keys
- RxSessionFilter: New servlet filter for per-request bean swapping (web.xml mapped)
- rxSessionInterceptor.js: AJAX interceptor injecting demographicNo into all Rx requests
- CaseManagementView2Action, RxChoosePatient2Action, RxShowAllergy2Action: Use new
  session methods instead of direct session attribute access
- RxWriteScript2Action: Add error handling for randomId parsing, String demographicNo setter
- ListDrugs.jsp: Multi-tab patient lookup from request parameter
- SearchDrug3.jsp, ViewScript.jsp, ViewScript2.jsp: Include interceptor, add resetStash,
  pass demographicNo through forms and iframes
- generatePreviewPDF.jsp: Use getFromSession/saveToSession

Original PR: openo-beta/Open-O#2261
Original Author: LiamStanziani

https://claude.ai/code/session_01D1MB9CvCDC4XaJGCXgxtB3
@LiamStanziani
Copy link
Copy Markdown
Collaborator Author

See latest comment on this PR for an explanation as to why this is being set back to draft: MagentaHealth#75

@LiamStanziani LiamStanziani marked this pull request as draft March 11, 2026 15:34
@LiamStanziani LiamStanziani changed the title Fix: missing meds when saving - LEGACY BUG Fix: missing staged meds when using save and print functionality with multiple different patient Rx related pages (Medications, Allergies) open - LEGACY BUG Mar 17, 2026
@LiamStanziani LiamStanziani marked this pull request as ready for review March 17, 2026 15:45
@LiamStanziani
Copy link
Copy Markdown
Collaborator Author

Will address and AI review comments that come in with setting this back to review

@qodo-code-review
Copy link
Copy Markdown

Review Summary by Qodo

Fix missing medications across multiple patient tabs by implementing per-patient Rx session isolation

🐞 Bug fix ✨ Enhancement

Grey Divider

Walkthroughs

Description
• Implement per-patient Rx session handling to prevent medications from mixing between multiple open
  patient tabs
• Add RxSessionFilter and rxSessionInterceptor to inject demographicNo into all Rx requests for
  correct patient context
• Improve error handling for invalid prescription identifiers and missing demographic numbers with
  400 responses
• Simplify special instructions logging and remove deprecated StringEscapeUtils usage
Diagram
flowchart LR
  A["Multiple Patient Tabs"] -->|demographicNo parameter| B["RxSessionFilter"]
  B -->|swaps correct bean| C["Per-Patient RxSessionBean"]
  C -->|keyed by demographicNo| D["Session Storage"]
  E["AJAX/Form Requests"] -->|rxSessionInterceptor| F["Add demographicNo"]
  F -->|inject into requests| B
  G["JSP Pages"] -->|include interceptor| E
  H["Error Handling"] -->|invalid IDs| I["400 Bad Request"]
Loading

Grey Divider

File Changes

1. src/main/java/ca/openosp/openo/prescript/pageUtil/RxSessionBean.java ✨ Enhancement +81/-0

Add per-patient session key helpers and legacy fallback

src/main/java/ca/openosp/openo/prescript/pageUtil/RxSessionBean.java


2. src/main/java/ca/openosp/openo/prescript/pageUtil/RxSessionFilter.java ✨ Enhancement +117/-0

New servlet filter for multi-tab Rx session isolation

src/main/java/ca/openosp/openo/prescript/pageUtil/RxSessionFilter.java


3. src/main/webapp/oscarRx/js/rxSessionInterceptor.js ✨ Enhancement +124/-0

New client-side interceptor for AJAX and form requests

src/main/webapp/oscarRx/js/rxSessionInterceptor.js


View more (12)
4. src/main/java/ca/openosp/openo/prescript/pageUtil/RxChoosePatient2Action.java 🐞 Bug fix +13/-4

Update to use per-patient session bean retrieval

src/main/java/ca/openosp/openo/prescript/pageUtil/RxChoosePatient2Action.java


5. src/main/java/ca/openosp/openo/prescript/pageUtil/RxShowAllergy2Action.java 🐞 Bug fix +12/-12

Refactor bean initialization with per-patient key support

src/main/java/ca/openosp/openo/prescript/pageUtil/RxShowAllergy2Action.java


6. src/main/java/ca/openosp/openo/prescript/pageUtil/RxWriteScript2Action.java 🐞 Bug fix +40/-4

Add error handling for invalid prescription IDs and demographic parsing

src/main/java/ca/openosp/openo/prescript/pageUtil/RxWriteScript2Action.java


7. src/main/java/ca/openosp/openo/prescript/data/RxPrescriptionData.java 🐞 Bug fix +4/-8

Simplify special instructions logging and remove deprecated escape utils

src/main/java/ca/openosp/openo/prescript/data/RxPrescriptionData.java


8. src/main/java/ca/openosp/openo/casemgmt/web/CaseManagementView2Action.java 🐞 Bug fix +14/-4

Update RxSessionBean initialization with per-patient key logic

src/main/java/ca/openosp/openo/casemgmt/web/CaseManagementView2Action.java


9. src/main/webapp/WEB-INF/web.xml ⚙️ Configuration changes +18/-1

Register RxSessionFilter for Rx pages and messenger preview

src/main/webapp/WEB-INF/web.xml


10. src/main/webapp/oscarRx/SearchDrug3.jsp ✨ Enhancement +18/-8

Add rxSessionInterceptor and improve demographicNo parameter handling

src/main/webapp/oscarRx/SearchDrug3.jsp


11. src/main/webapp/oscarRx/ListDrugs.jsp 🐞 Bug fix +28/-1

Retrieve patient data using demographicNo parameter for multi-tab support

src/main/webapp/oscarRx/ListDrugs.jsp


12. src/main/webapp/oscarRx/ViewScript.jsp ✨ Enhancement +17/-3

Add rxSessionInterceptor and implement safe stash clearing on close

src/main/webapp/oscarRx/ViewScript.jsp


13. src/main/webapp/oscarRx/ViewScript2.jsp ✨ Enhancement +23/-3

Add rxSessionInterceptor and safe stash clearing with fetch API

src/main/webapp/oscarRx/ViewScript2.jsp


14. src/main/webapp/messenger/generatePreviewPDF.jsp 🐞 Bug fix +12/-9

Update RxSessionBean initialization with per-patient key logic

src/main/webapp/messenger/generatePreviewPDF.jsp


15. src/main/webapp/WEB-INF/classes/struts.xml Formatting +1/-0

Minor formatting adjustment to struts configuration

src/main/webapp/WEB-INF/classes/struts.xml


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown

qodo-code-review bot commented Mar 17, 2026

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (1) 📎 Requirement gaps (0)

Grey Divider


Action required

1. demoNo unencoded in JS 📘 Rule violation ⛨ Security
Description
The new JavaScript assigns demoNo using raw JSP output (``) without context-appropriate OWASP
encoding. If demoNo can be influenced by request data, this can enable XSS in a JavaScript string
context.
Code

src/main/webapp/oscarRx/SearchDrug3.jsp[R1638-1641]

+        var demoNo='<%=demoNo%>';
      var data="drugId="+encodeURIComponent(id)+"&reason="+encodeURIComponent(reason)+"&comment="+encodeURIComponent(comment)+"&demoNo="+demoNo+"&drugSpecial="+encodeURIComponent(drugSpecial)+"&rand="+ Math.floor(Math.random()*10001);
          new Ajax.Request(url,{method: 'post',postBody:data,onSuccess:function(transport){
                var json=transport.responseText.evalJSON();
Evidence
Compliance requires OWASP encoding that matches the output context; here, untrusted data is written
into a JavaScript string without using Encode.forJavaScript(...) (or otherwise ensuring it is
strictly numeric and not interpreted as executable content).

CLAUDE.md
src/main/webapp/oscarRx/SearchDrug3.jsp[1638-1674]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`demoNo` is written into JavaScript using raw JSP output (`&amp;amp;lt;%=demoNo%&amp;amp;gt;`) without using context-appropriate OWASP encoding, which can enable XSS if the value is user-influenced.
## Issue Context
This value is placed inside a JavaScript string literal (`&amp;amp;#x27;...&amp;amp;#x27;`). Per policy, untrusted output must use the OWASP Encoder for the correct context (JavaScript).
## Fix Focus Areas
- src/main/webapp/oscarRx/SearchDrug3.jsp[1638-1674]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. demographic_no param ignored🐞 Bug ⛨ Security
Description
RxSessionFilter only reads the "demographicNo" parameter, but generatePreviewPDF.jsp still generates
PrintDrugProfile.jsp URLs with "demographic_no", so the filter won’t reliably swap in the correct
per-patient RxSessionBean for that request. PrintDrugProfile.jsp then uses session-scoped
RxSessionBean/Patient state, which can be from a different tab/patient and produce cross-patient
leakage/wrong output.
Code

src/main/java/ca/openosp/openo/prescript/pageUtil/RxSessionFilter.java[R63-66]

+        if (session != null) {
+            int demographicNo = parseDemographicNo(request.getParameter("demographicNo"));
+            boolean usedFallback = false;
+
Evidence
The filter explicitly parses only "demographicNo"; the messenger preview flow still links to
PrintDrugProfile.jsp with "demographic_no" (underscore), and PrintDrugProfile.jsp does not read that
request parameter—its content is driven by sessionScope.RxSessionBean and session "Patient". In a
multi-tab scenario, those session attributes can refer to a different patient than the one encoded
in the URL, causing wrong patient drug profiles and potential PHI leakage.

src/main/java/ca/openosp/openo/prescript/pageUtil/RxSessionFilter.java[63-66]
src/main/webapp/messenger/generatePreviewPDF.jsp[420-436]
src/main/webapp/oscarRx/PrintDrugProfile.jsp[37-45]
src/main/webapp/oscarRx/PrintDrugProfile.jsp[64-73]
src/main/webapp/oscarRx/PrintDrugProfile.jsp[90-104]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`RxSessionFilter` only looks for the request parameter `demographicNo`, but parts of the Rx/messenger flow still send `demographic_no` (underscore). As a result, the filter may not swap the correct per-patient `RxSessionBean` into the legacy key, and `PrintDrugProfile.jsp` relies on session-scoped `RxSessionBean` and session `Patient`, which can point at the wrong patient in multi-tab usage.
## Issue Context
`generatePreviewPDF.jsp` builds `PrintDrugProfile.jsp?demographic_no=...`, while the filter reads only `demographicNo`. `PrintDrugProfile.jsp` does not read `demographic_no` at all.
## Fix Focus Areas
- src/main/java/ca/openosp/openo/prescript/pageUtil/RxSessionFilter.java[63-66]
- src/main/webapp/messenger/generatePreviewPDF.jsp[420-436]
- src/main/webapp/oscarRx/PrintDrugProfile.jsp[37-45]
- src/main/webapp/oscarRx/PrintDrugProfile.jsp[90-104]
## Suggested approach
1. Update `RxSessionFilter` to accept both `demographicNo` and legacy `demographic_no` (and optionally `demoNo`) when parsing the demographic.
2. Update URL generation in `generatePreviewPDF.jsp` to include `demographicNo` (or switch entirely).
3. Update `PrintDrugProfile.jsp` to derive the patient context using the demographic from the request (via `LoggedInInfo` + `RxPatientData.getPatient(...)`) rather than session `Patient`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Legacy-only bean not migrated🐞 Bug ⛯ Reliability
Description
RxSessionFilter clears the legacy session key when a demographicNo is provided but no per-patient
bean exists, yet StaticScript2.jsp still stores RxSessionBean only under the legacy key. This
combination can cause Rx pages (e.g., SearchDrug3.jsp) to lose RxSessionBean and redirect to
error.html when navigating from StaticScript2 flows.
Code

src/main/java/ca/openosp/openo/prescript/pageUtil/RxSessionFilter.java[R75-84]

+            if (demographicNo > 0) {
+                RxSessionBean perPatientBean = (RxSessionBean) session.getAttribute(
+                        RxSessionBean.getSessionKey(demographicNo));
+                if (perPatientBean != null) {
+                    session.setAttribute(LEGACY_KEY, perPatientBean);
+                } else if (!usedFallback) {
+                    // demographicNo was explicitly provided but no per-patient bean exists.
+                    // Clear the legacy key to prevent cross-patient leakage from a stale bean.
+                    session.removeAttribute(LEGACY_KEY);
+                } else {
Evidence
The filter’s lookup path checks only the per-patient session attribute and removes the legacy
attribute if the per-patient attribute is missing. StaticScript2.jsp writes only the legacy
attribute (no per-patient key), and SearchDrug3.jsp hard-fails if sessionScope.RxSessionBean is
missing; therefore a request that includes demographicNo but came from a legacy-only writer can lose
the bean and error out. Although RxSessionBean.getFromSession() implements legacy-to-per-patient
migration, RxSessionFilter does not use it.

src/main/java/ca/openosp/openo/prescript/pageUtil/RxSessionFilter.java[75-84]
src/main/webapp/oscarRx/StaticScript2.jsp[78-85]
src/main/webapp/oscarRx/SearchDrug3.jsp[81-88]
src/main/java/ca/openosp/openo/prescript/pageUtil/RxSessionBean.java[69-79]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`RxSessionFilter` removes `RxSessionBean` (legacy key) when `demographicNo` is supplied but the per-patient key is missing. Some code paths (e.g., `StaticScript2.jsp`) still set only the legacy key, so subsequent Rx requests with `demographicNo` can have the bean removed and Rx pages/actions will redirect to `error.html`.
## Issue Context
There is already migration logic in `RxSessionBean.getFromSession(HttpSession,int)` to move a matching legacy bean into the per-patient key, but the filter bypasses it.
## Fix Focus Areas
- src/main/java/ca/openosp/openo/prescript/pageUtil/RxSessionFilter.java[75-84]
- src/main/webapp/oscarRx/StaticScript2.jsp[78-85]
- src/main/java/ca/openosp/openo/prescript/pageUtil/RxSessionBean.java[69-79]
## Suggested approach
1. Update `StaticScript2.jsp` to call `RxSessionBean.saveToSession(session, rxBean)` instead of `setAttribute(&amp;amp;quot;RxSessionBean&amp;amp;quot;, rxBean)`.
2. Update `RxSessionFilter` to fetch the bean using `RxSessionBean.getFromSession(session, demographicNo)` so legacy-only beans are migrated rather than treated as missing.
3. Reconsider/limit `session.removeAttribute(LEGACY_KEY)` to only when a non-matching legacy bean exists (to avoid breaking flows).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (1)
4. Session swap race 🐞 Bug ⛨ Security
Description
RxSessionFilter mutates the shared session attribute "RxSessionBean" per request, which can be
overwritten by concurrent requests from other tabs and cause in-flight Rx actions/JSP rendering to
read the wrong patient's bean. This leaves a multi-tab cross-patient leakage risk despite
per-patient keys.
Code

src/main/java/ca/openosp/openo/prescript/pageUtil/RxSessionFilter.java[R75-80]

+            if (demographicNo > 0) {
+                RxSessionBean perPatientBean = (RxSessionBean) session.getAttribute(
+                        RxSessionBean.getSessionKey(demographicNo));
+                if (perPatientBean != null) {
+                    session.setAttribute(LEGACY_KEY, perPatientBean);
+                } else if (!usedFallback) {
Evidence
The filter rewrites the legacy session key on every request; meanwhile, Rx pages like
SearchDrug3.jsp both (a) read from sessionScope.RxSessionBean and (b) initiate multiple asynchronous
Ajax requests. With multiple tabs, servlet containers can process requests concurrently for the same
HttpSession, so one request can change the legacy key while another request is still
executing/rendering and reading it, leading to cross-patient data access.

src/main/java/ca/openosp/openo/prescript/pageUtil/RxSessionFilter.java[75-80]
src/main/webapp/oscarRx/SearchDrug3.jsp[81-86]
src/main/webapp/oscarRx/SearchDrug3.jsp[281-289]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`RxSessionFilter` swaps the legacy session attribute `RxSessionBean` to point at the current patient’s bean. With multiple tabs and concurrent AJAX requests, this shared session attribute can be overwritten mid-request, causing actions/JSPs to read the wrong patient bean and leak/modify data across patients.
## Issue Context
Rx pages (e.g., `SearchDrug3.jsp`) both render using `sessionScope.RxSessionBean` and make multiple asynchronous requests, increasing concurrency probability.
## Fix Focus Areas
- src/main/java/ca/openosp/openo/prescript/pageUtil/RxSessionFilter.java[75-80]
- src/main/webapp/oscarRx/SearchDrug3.jsp[81-86]
## Suggested approach
1. Stop mutating the session-wide legacy key as the primary routing mechanism. Prefer retrieving the correct bean from the per-patient key using `demographicNo` and passing it via request attributes.
2. As an incremental step, set a request attribute (e.g., `request.setAttribute(&amp;amp;quot;RxSessionBean&amp;amp;quot;, perPatientBean)`) and update JSPs/actions to read from request/pageContext first (before sessionScope).
3. Longer-term: migrate remaining code away from `session.getAttribute(&amp;amp;quot;RxSessionBean&amp;amp;quot;)` to `RxSessionBean.getFromSession(session, demographicNo)` (or equivalent), eliminating the legacy alias reliance.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Copy link
Copy Markdown

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • In rxSessionInterceptor.js, the fetch wrapper only appends demographicNo via the URL and doesn’t handle Request objects or bodies that might already carry the parameter; consider detecting Request instances and preserving/augmenting their query/body rather than coercing to a string URL to avoid subtle bugs with more complex fetch usages.
  • RxSessionFilter’s fallback behaviour when demographicNo is absent (or invalid) but a legacy RxSessionBean exists leaves the legacy bean in place and logs a warning only when a per-patient bean lookup fails with a fallback demographic; you might want to make the conditions and logging more explicit (e.g., distinguish between ‘no per-patient bean yet’ vs. ‘stale bean for another patient’) to simplify future debugging of cross-patient leakage scenarios.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In rxSessionInterceptor.js, the fetch wrapper only appends demographicNo via the URL and doesn’t handle Request objects or bodies that might already carry the parameter; consider detecting Request instances and preserving/augmenting their query/body rather than coercing to a string URL to avoid subtle bugs with more complex fetch usages.
- RxSessionFilter’s fallback behaviour when demographicNo is absent (or invalid) but a legacy RxSessionBean exists leaves the legacy bean in place and logs a warning only when a per-patient bean lookup fails with a fallback demographic; you might want to make the conditions and logging more explicit (e.g., distinguish between ‘no per-patient bean yet’ vs. ‘stale bean for another patient’) to simplify future debugging of cross-patient leakage scenarios.

## Individual Comments

### Comment 1
<location path="src/main/webapp/oscarRx/js/rxSessionInterceptor.js" line_range="80-89" />
<code_context>
+        };
+    }
+
+    // Intercept fetch API
+    if (typeof window.fetch === 'function') {
+        var originalFetch = window.fetch;
+        window.fetch = function(url, options) {
+            options = options || {};
+            var urlStr = (url instanceof Request) ? url.url : String(url);
+            if (urlStr.indexOf('demographicNo=') === -1) {
+                var separator = urlStr.indexOf('?') === -1 ? '?' : '&';
+                url = urlStr + separator + 'demographicNo=' + encodeURIComponent(demoNo);
+            }
+            return originalFetch.call(this, url, options);
+        };
+    }
</code_context>
<issue_to_address>
**issue (bug_risk):** The fetch wrapper discards Request objects and may change behavior of existing fetch callers.

When callers pass a `Request` (e.g., `fetch(new Request(...), options)`), this wrapper replaces it with a URL string and `options || {}`, discarding method, headers, body, credentials, mode, etc. This can break existing code that relies on `Request` instances. To keep behavior transparent, if `url` is a `Request`, create a new `Request` with the modified URL and the original request as init (e.g., `new Request(modifiedUrl, url)`), and pass that to `originalFetch`. Only use the current string-based logic when `url` is not a `Request`.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread src/main/webapp/oscarRx/js/rxSessionInterceptor.js Outdated
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

11 issues found across 15 files

Confidence score: 2/5

  • There is clear high user-impact risk: several high-confidence findings show patient context can still bleed across tabs (RxSessionFilter, RxSessionBean, generatePreviewPDF.jsp, SearchDrug3.jsp), which can surface or act on the wrong patient’s medication data.
  • A concrete regression risk remains in request handling: rxSessionInterceptor.js can downgrade Request objects to plain URL strings, potentially dropping method/headers/body and breaking POST-based flows silently.
  • Integration points still look unsafe as wired: web.xml filter ordering can allow rejected requests to mutate Rx session state, and RxWriteScript2Action.java type mismatch may leave binding at demographic 0.
  • Pay close attention to src/main/java/ca/openosp/openo/prescript/pageUtil/RxSessionFilter.java, src/main/webapp/messenger/generatePreviewPDF.jsp, src/main/webapp/oscarRx/js/rxSessionInterceptor.js, and src/main/webapp/WEB-INF/web.xml - they drive the highest-risk patient-context and request-flow regressions.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/main/webapp/oscarRx/ViewScript.jsp">

<violation number="1" location="src/main/webapp/oscarRx/ViewScript.jsp:182">
P2: Handle rejected stash-clear requests before calling `clearPending('close')`; otherwise the Back to Oscar button stops working when the POST fails.</violation>
</file>

<file name="src/main/webapp/oscarRx/js/rxSessionInterceptor.js">

<violation number="1" location="src/main/webapp/oscarRx/js/rxSessionInterceptor.js:88">
P1: When `url` is a `Request` object, reassigning it to a plain string discards the request's method, headers, body, and credentials. A `fetch(new Request('/api', {method:'POST', body:...}))` call would silently become a bare GET. Preserve the `Request` by constructing a new one with the modified URL.</violation>
</file>

<file name="src/main/java/ca/openosp/openo/prescript/pageUtil/RxSessionFilter.java">

<violation number="1" location="src/main/java/ca/openosp/openo/prescript/pageUtil/RxSessionFilter.java:79">
P1: Swapping the active patient bean through a shared `HttpSession` attribute is still race-prone across concurrent tabs, so overlapping Rx requests can still read or clear the wrong patient's `RxSessionBean`.</violation>
</file>

<file name="src/main/java/ca/openosp/openo/prescript/pageUtil/RxWriteScript2Action.java">

<violation number="1" location="src/main/java/ca/openosp/openo/prescript/pageUtil/RxWriteScript2Action.java:1584">
P1: Keep `demographicNo` as an `int` property. This mismatched `String` setter can prevent Struts from binding the request parameter at all, leaving the action on demographic `0`.</violation>
</file>

<file name="src/main/webapp/WEB-INF/web.xml">

<violation number="1" location="src/main/webapp/WEB-INF/web.xml:40">
P1: Move `RxSessionFilter` after the auth/CSRF filters; right now rejected requests can still mutate the Rx session.</violation>
</file>

<file name="src/main/webapp/messenger/generatePreviewPDF.jsp">

<violation number="1" location="src/main/webapp/messenger/generatePreviewPDF.jsp:416">
P1: This only makes `RxSessionBean` per-patient; `PrintDrugProfile.jsp` still uses the shared session `Patient`, so multi-tab previews can still render the wrong patient.</violation>

<violation number="2" location="src/main/webapp/messenger/generatePreviewPDF.jsp:425">
P1: The preview request still uses `demographic_no`, so the new RxSessionFilter never selects the per-patient bean for `PrintDrugProfile.jsp`.</violation>
</file>

<file name="src/main/webapp/oscarRx/ViewScript2.jsp">

<violation number="1" location="src/main/webapp/oscarRx/ViewScript2.jsp:274">
P1: Use the LightWindow close API here instead of `parent.window.close()`, or the Back to Oscar action can leave the modal open / target the wrong window.</violation>
</file>

<file name="src/main/webapp/oscarRx/SearchDrug3.jsp">

<violation number="1" location="src/main/webapp/oscarRx/SearchDrug3.jsp:241">
P1: This page still renders `prescribedDrugs` from the shared session `Patient` object, so another Rx tab can still make the medication list show the wrong patient despite the new `demographicNo` propagation.</violation>
</file>

<file name="src/main/java/ca/openosp/openo/prescript/pageUtil/RxSessionBean.java">

<violation number="1" location="src/main/java/ca/openosp/openo/prescript/pageUtil/RxSessionBean.java:109">
P1: Updating the shared legacy session key here still lets no-`demographicNo` requests switch to the wrong patient's Rx session.</violation>
</file>

<file name="src/main/webapp/oscarRx/ListDrugs.jsp">

<violation number="1" location="src/main/webapp/oscarRx/ListDrugs.jsp:93">
P2: This fallback never runs when `getPatient(...)` fails, because that API returns a non-null wrapper with a null demographic. Check for `patient.getDemographic() == null` too, otherwise invalid `demographicNo` values fall through with `-1` and the page can load the wrong/empty medication list.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread src/main/webapp/oscarRx/js/rxSessionInterceptor.js Outdated
Comment thread src/main/webapp/WEB-INF/web.xml
Comment thread src/main/webapp/messenger/generatePreviewPDF.jsp Outdated
Comment thread src/main/webapp/oscarRx/ViewScript2.jsp Outdated
Comment thread src/main/webapp/oscarRx/SearchDrug3.jsp Outdated
Comment thread src/main/webapp/oscarRx/ViewScript.jsp Outdated
Comment thread src/main/webapp/oscarRx/ListDrugs.jsp Outdated
  - Move RxSessionFilter after auth filters in web.xml to prevent
    unauthenticated session mutation
  - Add Patient session attribute swapping to RxSessionFilter, removing
    redundant manual lookups in ListDrugs.jsp
  - Support both demographicNo and demographic_no params in filter
  - Fix fetch interceptor to preserve Request object properties
  - Revert generatePreviewPDF.jsp bean read to use filter-swapped legacy key
  - Remove deferred stash clearing fix (resetStashAndClose) from
    ViewScript.jsp and ViewScript2.jsp
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5 issues found across 7 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/main/webapp/WEB-INF/web.xml">

<violation number="1" location="src/main/webapp/WEB-INF/web.xml:159">
P1: `RxSessionFilter` now runs after Struts for `/oscarRx/*` and `/CaseManagementView.do`, so the per-patient bean swap happens too late to protect those actions.</violation>
</file>

<file name="src/main/webapp/oscarRx/ListDrugs.jsp">

<violation number="1" location="src/main/webapp/oscarRx/ListDrugs.jsp:69">
P1: Resolve the patient from `demographicNo` on this request instead of the shared session `Patient`; otherwise concurrent Rx tabs can still render another patient's drug list.</violation>
</file>

<file name="src/main/webapp/oscarRx/ViewScript2.jsp">

<violation number="1" location="src/main/webapp/oscarRx/ViewScript2.jsp:843">
P2: Back-to-Oscar no longer clears the stored ReRx selection list, so stale renewal checkboxes can leak into the next Rx session for this patient.</violation>

<violation number="2" location="src/main/webapp/oscarRx/ViewScript2.jsp:843">
P1: Don't close the popup immediately after submitting `clearPending('close')`; it can abort the stash-clear request.</violation>
</file>

<file name="src/main/java/ca/openosp/openo/prescript/pageUtil/RxSessionFilter.java">

<violation number="1" location="src/main/java/ca/openosp/openo/prescript/pageUtil/RxSessionFilter.java:103">
P1: Clear the session `Patient` when the requested demographic cannot be loaded; otherwise stale patient data can still be used for the request.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread src/main/webapp/WEB-INF/web.xml Outdated
Comment thread src/main/webapp/oscarRx/ListDrugs.jsp
Comment thread src/main/webapp/oscarRx/ViewScript2.jsp
Comment thread src/main/webapp/oscarRx/ViewScript2.jsp
  - Revert RxSessionFilter mappings to before Struts2 in web.xml.
    Struts2 short-circuits chain.doFilter() for .do action URLs,
    so placing the filter after Struts2 prevented bean swapping
    for actions like RxWriteScript2Action. Auth for .do URLs is
    handled by SecurityInfoManager inside actions, not LoginFilter.
  - Simplify CaseManagementView2Action and RxChoosePatient2Action
    bean setup — remove redundant getFromSession lookups since
    the filter handles per-request swapping.
  - Restore RxShowAllergy2Action's original provider/demographic
    match check to preserve existing bean state (stash, view).
  - All three actions now use saveToSession instead of setAttribute
    for per-patient key storage.
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5 issues found across 4 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/main/java/ca/openosp/openo/casemgmt/web/CaseManagementView2Action.java">

<violation number="1" location="src/main/java/ca/openosp/openo/casemgmt/web/CaseManagementView2Action.java:459">
P1: Reinitializing `RxSessionBean` here drops any staged prescriptions already stored for this patient.</violation>
</file>

<file name="src/main/java/ca/openosp/openo/prescript/pageUtil/RxShowAllergy2Action.java">

<violation number="1" location="src/main/java/ca/openosp/openo/prescript/pageUtil/RxShowAllergy2Action.java:178">
P1: Compare provider numbers by value, not by `String` identity, or this branch can recreate the session bean and lose staged Rx state for the same provider.</violation>

<violation number="2" location="src/main/java/ca/openosp/openo/prescript/pageUtil/RxShowAllergy2Action.java:186">
P2: Validate `demographicNo` before parsing it; these direct `Integer.parseInt` calls now crash the action on malformed input.</violation>
</file>

<file name="src/main/java/ca/openosp/openo/prescript/pageUtil/RxChoosePatient2Action.java">

<violation number="1" location="src/main/java/ca/openosp/openo/prescript/pageUtil/RxChoosePatient2Action.java:85">
P1: Recreating the RxSessionBean here wipes the existing per-patient stash instead of reusing it.</violation>

<violation number="2" location="src/main/java/ca/openosp/openo/prescript/pageUtil/RxChoosePatient2Action.java:87">
P2: Restore validation around `demographicNo`; this inline parse now turns bad input into an unhandled 500.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread src/main/java/ca/openosp/openo/prescript/pageUtil/RxShowAllergy2Action.java Outdated
Comment thread src/main/java/ca/openosp/openo/prescript/pageUtil/RxShowAllergy2Action.java Outdated
Comment thread src/main/java/ca/openosp/openo/prescript/pageUtil/RxChoosePatient2Action.java Outdated
@sebastian-j-ibanez sebastian-j-ibanez changed the base branch from hotfix/01232026 to maintenance March 20, 2026 16:03
@sebastian-j-ibanez
Copy link
Copy Markdown
Collaborator

sebastian-j-ibanez commented Mar 20, 2026

@LiamStanziani just want to confirm: is this PR still being worked on? ready for review/merge?

@sebastian-j-ibanez sebastian-j-ibanez changed the base branch from maintenance to hotfix/01232026 March 20, 2026 17:16
@LiamStanziani
Copy link
Copy Markdown
Collaborator Author

LiamStanziani commented Mar 20, 2026

@sebastian-j-ibanez This PR is currently waiting for testing by Carmen, not currently working on it at the moment but I might need to update it later on if something comes up.

Here is the other PR that I expect to be tested (which is the same branch but just going towards another base branch), if this goes well then this will be merged by Carmen: MagentaHealth#75

@LiamStanziani LiamStanziani changed the base branch from hotfix/01232026 to develop April 16, 2026 15:40
Resolved Conflicts:
	src/main/java/ca/openosp/openo/prescript/data/RxPrescriptionData.java
	src/main/webapp/oscarRx/SearchDrug3.jsp
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 16, 2026

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Snapshot Warnings

⚠️: No snapshots were found for the head SHA 910f52c.
Ensure that dependencies are being submitted on PR branches and consider enabling retry-on-snapshot-warnings. See the documentation for more information and troubleshooting advice.

Scanned Files

None

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Staged prescriptions lost when opening Rx related pages for multiple patients

4 participants