[MIRTH-3991] Saving mirth.properties while Server Manager is open can cause corruption Created: 24/Jun/16  Updated: 29/Jun/16  Resolved: 24/Jun/16

Status: Closed
Project: Mirth Connect
Component/s: Server, Server Manager
Affects Version/s: 3.0.3, 3.1.1, 3.2.2, 3.3.2, 3.4.1
Fix Version/s: 3.5.0, 3.4.2

Type: Bug Priority: Major
Reporter: Nick Rupley Assignee: Nick Rupley
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Attachments: PNG File error.png     File mirth.corrupted.properties     PNG File newPrompt.png    
Assigned QA: Minh Tran

 Description   
  • Open the Server Manager.
  • While the manager is still open, open up mirth.properties in an editor and save it.
  • Go back to the manager, make some change, and hit Apply.

These steps will usually cause mirth.properties to wig out. In particular, the protocol / cipher suite entries will for some reason decouple into multiple lines, causing HTTPS traffic between the client and server to fail.

As a workaround, just make sure to close (do not hit OK or Apply) the server manager and tray icon and reopen it whenever you want to make any changes using it.



 Comments   
Comment by Nick Rupley [ 24/Jun/16 ]

Fixed in revisions 8068/8069. Now whenever saving properties, the manager will first check whether they have changed, and prompt the user to overwrite first. If the user accepts, the manager will first reload the layout before saving anything new.

Migrate3_4_0 was previously always saving the properties even if nothing changed. Now we only do that if "sqlserver2000" appears in the comment.

The configuration controller will now use getStringArray to read the protocol / cipher suite properties, just in case they have decoupled for whatever reason.

Comment by Minh Tran [ 29/Jun/16 ]

OS(s) and JRE version: virtual Window 7 with JRE version 1.8.0_91-b14
Version(s)/Build(s) to reproduce failure: mirthconnect-3.4.1.8057.b139-windows-x64
Version(s)/Build(s) to verify fixes: mirthconnect-3.5.0.8075.b1998-windows-x64.exe
How Tested:

  1. Launch & Open Mirth Connect Server Manager
  2. From Window Explorer, go to <mirth install>/conf/, make a copy of mirth.properties (save as .original)
  3. Open mirth.properties in editor, make some comments, save changes and exit editor
  4. Back to Server Manager, make changes to Server > Log Level > select Apply
  5. Verify content of the current mirth.properties vs. the original copy
  6. Restart Mirth Connect service
  7. Launch Administrator
  8. Verify if able to launch and login

Observation:
Before fixes:

  1. After the above steps, mirth.properties file would get corrupted (file size changed from 4KB -> 6KB).
  2. See attached corrupted.mirth.properties file
  3. If user happens to restart Mirth Connect, user won't be able to log into Administrator with Error and this exception in Client (java) log
    com.mirth.connect.client.core.ClientException: javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
    	at com.mirth.connect.client.core.ServerConnection.executeSync(ServerConnection.java:221)
    	at com.mirth.connect.client.core.ServerConnection.apply(ServerConnection.java:144)
    	at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:255)
    	at org.glassfish.jersey.client.JerseyInvocation$3.call(JerseyInvocation.java:722)
    	at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
    	at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
    	at org.glassfish.jersey.internal.Errors.process(Errors.java:228)
    	at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:444)
    	at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:718)
    	at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:459)
    	at org.glassfish.jersey.client.proxy.WebResourceFactory.invoke(WebResourceFactory.java:379)
    	at com.sun.proxy.$Proxy13.login(Unknown Source)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    	at java.lang.reflect.Method.invoke(Unknown Source)
    	at com.mirth.connect.client.core.Client$2.invoke(Client.java:249)
    	at com.sun.proxy.$Proxy13.login(Unknown Source)
    	at com.mirth.connect.client.core.Client.login(Client.java:301)
    	at com.mirth.connect.client.ui.LoginPanel$8.doInBackground(LoginPanel.java:425)
    	at com.mirth.connect.client.ui.LoginPanel$8.doInBackground(LoginPanel.java:412)
    	at javax.swing.SwingWorker$1.call(Unknown Source)
    	at java.util.concurrent.FutureTask.run(Unknown Source)
    	at javax.swing.SwingWorker.run(Unknown Source)
    	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    	at java.lang.Thread.run(Unknown Source)

Verify Fixed:
With the latest revision:

  1. Server Manager prompted to overwrite before "Apply" changes in Server Manager
  2. mirth.properties file was updated properly, no corruption found
  3. Even when a corrupted mirth.properties file is in place (copy from older build), was still be able to log into Administrator Console, Exception in Client (java) log
    Exception in thread "AWT-EventQueue-2" java.lang.NullPointerException
    	at javax.swing.plaf.basic.BasicTextFieldUI.getBaseline(Unknown Source)
    	at javax.swing.JComponent.getBaseline(Unknown Source)
    	at javax.swing.GroupLayout$ComponentSpring.getBaseline(Unknown Source)
    	at javax.swing.GroupLayout$BaselineGroup.calculateBaselineAndResizeBehavior(Unknown Source)
    	at javax.swing.GroupLayout$BaselineGroup.calculateSize(Unknown Source)
    	at javax.swing.GroupLayout$Group.calculateMinimumSize(Unknown Source)
    	at javax.swing.GroupLayout$ParallelGroup.calculateMinimumSize(Unknown Source)
    	at javax.swing.GroupLayout$Spring.getMinimumSize(Unknown Source)
    	at javax.swing.GroupLayout$Group.getSpringSize(Unknown Source)
    	at javax.swing.GroupLayout$Group.calculateSize(Unknown Source)
    	at javax.swing.GroupLayout$Group.calculateMinimumSize(Unknown Source)
    	at javax.swing.GroupLayout$ParallelGroup.calculateMinimumSize(Unknown Source)
    	at javax.swing.GroupLayout$Spring.getMinimumSize(Unknown Source)
    	at javax.swing.GroupLayout$Group.getSpringSize(Unknown Source)
    	at javax.swing.GroupLayout$Group.calculateSize(Unknown Source)
    	at javax.swing.GroupLayout$Group.calculateMinimumSize(Unknown Source)
    	at javax.swing.GroupLayout$Spring.getMinimumSize(Unknown Source)
    	at javax.swing.GroupLayout$Group.getSpringSize(Unknown Source)
    	at javax.swing.GroupLayout$Group.calculateSize(Unknown Source)
    	at javax.swing.GroupLayout$Group.calculateMinimumSize(Unknown Source)
    	at javax.swing.GroupLayout$ParallelGroup.calculateMinimumSize(Unknown Source)
    	at javax.swing.GroupLayout$Spring.getMinimumSize(Unknown Source)
    	at javax.swing.GroupLayout$Group.getSpringSize(Unknown Source)
    	at javax.swing.GroupLayout$Group.calculateSize(Unknown Source)
    	at javax.swing.GroupLayout$Group.calculateMinimumSize(Unknown Source)
    	at javax.swing.GroupLayout$Spring.getMinimumSize(Unknown Source)
    	at javax.swing.GroupLayout.calculateAutopadding(Unknown Source)
    	at javax.swing.GroupLayout.prepare(Unknown Source)
    	at javax.swing.GroupLayout.minimumLayoutSize(Unknown Source)
    	at java.awt.Container.minimumSize(Unknown Source)
    	at java.awt.Container.getMinimumSize(Unknown Source)
    	at javax.swing.JComponent.getMinimumSize(Unknown Source)
    	at javax.swing.GroupLayout$ComponentSpring.calculateNonlinkedMinimumSize(Unknown Source)
    	at javax.swing.GroupLayout$ComponentSpring.calculateMinimumSize(Unknown Source)
    	at javax.swing.GroupLayout$Spring.getMinimumSize(Unknown Source)
    	at javax.swing.GroupLayout$ComponentSpring.calculatePreferredSize(Unknown Source)
    	at javax.swing.GroupLayout$Spring.getPreferredSize(Unknown Source)
    	at javax.swing.GroupLayout$Group.getSpringSize(Unknown Source)
    	at javax.swing.GroupLayout$Group.calculateSize(Unknown Source)
    	at javax.swing.GroupLayout$Group.calculatePreferredSize(Unknown Source)
    	at javax.swing.GroupLayout$Spring.getPreferredSize(Unknown Source)
    	at javax.swing.GroupLayout$Group.getSpringSize(Unknown Source)
    	at javax.swing.GroupLayout$Group.calculateSize(Unknown Source)
    	at javax.swing.GroupLayout$Group.calculatePreferredSize(Unknown Source)
    	at javax.swing.GroupLayout$Spring.getPreferredSize(Unknown Source)
    	at javax.swing.GroupLayout$SequentialGroup.setValidSize(Unknown Source)
    	at javax.swing.GroupLayout$Group.setSize(Unknown Source)
    	at javax.swing.GroupLayout.layoutContainer(Unknown Source)
    	at java.awt.Container.layout(Unknown Source)
    	at java.awt.Container.doLayout(Unknown Source)
    	at java.awt.Container.validateTree(Unknown Source)
    	at java.awt.Container.validateTree(Unknown Source)
    	at java.awt.Container.validateTree(Unknown Source)
    	at java.awt.Container.validateTree(Unknown Source)
    	at java.awt.Container.validate(Unknown Source)
    	at java.awt.Window.dispatchEventImpl(Unknown Source)
    	at java.awt.Component.dispatchEvent(Unknown Source)
    	at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    	at java.awt.EventQueue.access$500(Unknown Source)
    	at java.awt.EventQueue$3.run(Unknown Source)
    	at java.awt.EventQueue$3.run(Unknown Source)
    	at java.security.AccessController.doPrivileged(Native Method)
    	at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    	at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    	at java.awt.EventQueue$4.run(Unknown Source)
    	at java.awt.EventQueue$4.run(Unknown Source)
    	at java.security.AccessController.doPrivileged(Native Method)
    	at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    	at java.awt.EventQueue.dispatchEvent(Unknown Source)
    	at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    	at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    	at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    	at java.awt.EventDispatchThread.run(Unknown Source)
  4. Also observed no corruption with log4j.properties when making changes via Text Editor
Comment by Minh Tran [ 29/Jun/16 ]

Verified with mirthconnect-3.5.0.8075.b1998-windows-x64.exe

  1. mirth.properties wont get corrupted when make changes via Text Editor and Server Manager
  2. Server Manager will now prompt for Overwrite when there are changes to mirth.properties file
  3. User still able to log into Administrator even when mirth.properties corrupted (with multiple lines of protocol/cipher suite)
Generated at Sat Aug 24 21:17:41 PDT 2019 using JIRA 6.2.7#6265-sha1:91604a8de81892a3e362e0afee505432f29579b0.