Bug 252708 - [api] Saving Profile Job happens when not changing Property Values on Connections
Summary: [api] Saving Profile Job happens when not changing Property Values on Connect...
Status: RESOLVED FIXED
Alias: None
Product: Target Management
Classification: Tools
Component: RSE (show other bugs)
Version: 3.0.1   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 3.1 M3   Edit
Assignee: David McKnight CLA
QA Contact: Martin Oberhuber CLA
URL:
Whiteboard:
Keywords: api
Depends on:
Blocks:
 
Reported: 2008-10-29 21:56 EDT by Kevin Doyle CLA
Modified: 2008-11-12 13:21 EST (History)
2 users (show)

See Also:


Attachments
patch to check whether there are changes before committing (12.18 KB, patch)
2008-11-05 15:56 EST, David McKnight CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Kevin Doyle CLA 2008-10-29 21:56:49 EDT
When viewing the property pages for a connection and clicking okay, without changing any of the values, a saving profile job is started.  This happens for all 3 property pages: Connector Service, Host, and Subsystems.
Comment 1 Kevin Doyle CLA 2008-10-29 22:07:12 EDT
Appears to happen on Subsystems for the Service property page.

Filters when looking at the filter property page.

Shells and the Environment Variables.
Comment 2 Martin Oberhuber CLA 2008-10-30 10:09:10 EDT
This is important for us, too.
Comment 3 David McKnight CLA 2008-11-05 15:56:30 EST
Created attachment 117141 [details]
patch to check whether there are changes before committing

This patch contains changes for the service pages, the connection page, the environment variables and the filter property page to only do a commit if there is an actual change.

Could you try this out to make sure this handles all the cases you've seen this with?
Comment 4 Kevin Doyle CLA 2008-11-06 17:20:26 EST
The subsystem property page on the files subsystem is still causing a save.

Also on the Host property page we hide the default encoding, so this line is now giving a NPE:

if (!isRemoteEncoding && !encoding.equals(currentEncoding)) {
Comment 5 David McKnight CLA 2008-11-06 18:02:20 EST
(In reply to comment #4)
> The subsystem property page on the files subsystem is still causing a save.
> 
> Also on the Host property page we hide the default encoding, so this line is
> now giving a NPE:
> 
> if (!isRemoteEncoding && !encoding.equals(currentEncoding)) {
> 

I can add a check for the null encoding on the host property page.  

For the subsystem property page, the user id is always being seen as changed because the default displayed one is based on Subsystem.getLocalUserId() while it's being compared with IConnectorService.getUserId() and these aren't the same.  I need a better understanding as to why we have both of these and how they should be used in this scenario before committing to a solution for this.  Could you open a separate defect for this?
Comment 6 Kevin Doyle CLA 2008-11-06 21:04:55 EST
(In reply to comment #5)
> I can add a check for the null encoding on the host property page.  

Let's add the check then we can resolve this bug.

> For the subsystem property page, the user id is always being seen as changed
> because the default displayed one is based on Subsystem.getLocalUserId() while
> it's being compared with IConnectorService.getUserId() and these aren't the
> same.  I need a better understanding as to why we have both of these and how
> they should be used in this scenario before committing to a solution for this. 
> Could you open a separate defect for this?

Bug 254548 has been opened for this.
Comment 7 David McKnight CLA 2008-11-07 08:30:49 EST
(In reply to comment #6)
> (In reply to comment #5)
> > I can add a check for the null encoding on the host property page.  
> 
> Let's add the check then we can resolve this bug.
> 


I've committed the changes and the check for the null encoding.  I will address the subsystem property page issue in bug 254548.

Comment 8 Martin Oberhuber CLA 2008-11-07 15:50:50 EST
hasConnectionChanged() looks suspicious because IHost.getDescription() can be null (and actually is null by default). I'd assume that getDefaultUserId() and getHostName() can also be null for connection types that don't have a concept of user/password, or connect by means other than TCP/IP (such as serial).

I'd recommend introducing a compareStrings(s1,s2) method which is robust against null Strings.
Comment 9 Martin Oberhuber CLA 2008-11-07 15:56:21 EST
Also, ServiceElement#	protected boolean _childChanged is new API. Please add an @since tag, and enable API Tooling in order to see such errors in your workspace.
Comment 10 Martin Oberhuber CLA 2008-11-07 16:03:03 EST
Also, in RemoteCmdSubSystem#areVariablesTheSame() you'll likely need to sort the keys before you compare them (not 100%sure, but Arrays.sort() is simple to call, don't forget to clone the input argument before sorting). PropertySets are HashMaps, and the order produced by the keySet() is undefined (even on a clone, I think).
Comment 11 David McKnight CLA 2008-11-07 16:19:22 EST
(In reply to comment #8)
> hasConnectionChanged() looks suspicious because IHost.getDescription() can be
> null (and actually is null by default). I'd assume that getDefaultUserId() and
> getHostName() can also be null for connection types that don't have a concept
> of user/password, or connect by means other than TCP/IP (such as serial).
> 
> I'd recommend introducing a compareStrings(s1,s2) method which is robust
> against null Strings.
> 

For the compare strings are you thinking something like this?

	private boolean hasConnectionChanged(IHost conn){
		if (!compareStrings(conn.getName(), form.getConnectionName()) ||
		!compareStrings(conn.getHostName(), form.getHostName()) ||
		!compareStrings(conn.getDescription(), form.getConnectionDescription()) ||
		!compareStrings(conn.getDefaultUserId(), form.getDefaultUserId())){
			return true;
		}
		return false;	    			  
	}
	
	private boolean compareStrings(String str1, String str2){
		if (str1 == null)
			return (str2 == null);
		else 
			return (str2 == null) ? false: str1.equals(str2);
	}


In the case of the description it's stored as "" rather than null but I guess null could come up.
Comment 12 David McKnight CLA 2008-11-07 16:24:27 EST
(In reply to comment #9)
> Also, ServiceElement#   protected boolean _childChanged is new API. Please add
> an @since tag, and enable API Tooling in order to see such errors in your
> workspace.
> 

I've added the @since tag.
Comment 13 Martin Oberhuber CLA 2008-11-07 16:31:15 EST
DummyHost has description==null, and class Host initialized description==null.
Persistence providers are pluggable, so a "null" description seems likely IMHO.

I think that your compareStrings() method should likely treat "" and null as equal, since the Form will likely not accept null in any of its SWT fields but replace null by "" when initializing the fields.
Comment 14 David McKnight CLA 2008-11-07 16:38:19 EST
(In reply to comment #10)
> Also, in RemoteCmdSubSystem#areVariablesTheSame() you'll likely need to sort
> the keys before you compare them (not 100%sure, but Arrays.sort() is simple to
> call, don't forget to clone the input argument before sorting). PropertySets
> are HashMaps, and the order produced by the keySet() is undefined (even on a
> clone, I think).
> 

Hmm... I didn't want to sort anything because one change a user can make to the environment variables page is moving variables up and down in the list - so if the order changes, a save is needed.  From my tests the current code seems to work okay but I guess I should check again to make sure this is predictable and consistent.
Comment 15 David McKnight CLA 2008-11-07 16:56:04 EST
(In reply to comment #13)
> DummyHost has description==null, and class Host initialized description==null.
> Persistence providers are pluggable, so a "null" description seems likely IMHO.
> 
> I think that your compareStrings() method should likely treat "" and null as
> equal, since the Form will likely not accept null in any of its SWT fields but
> replace null by "" when initializing the fields.
> 

I've update cvs with the new compareStrings method.
Comment 16 David McKnight CLA 2008-11-07 17:05:06 EST
(In reply to comment #14)
> (In reply to comment #10)
> > Also, in RemoteCmdSubSystem#areVariablesTheSame() you'll likely need to sort
> > the keys before you compare them (not 100%sure, but Arrays.sort() is simple to
> > call, don't forget to clone the input argument before sorting). PropertySets
> > are HashMaps, and the order produced by the keySet() is undefined (even on a
> > clone, I think).
> > 
> 
> Hmm... I didn't want to sort anything because one change a user can make to the
> environment variables page is moving variables up and down in the list - so if
> the order changes, a save is needed.  From my tests the current code seems to
> work okay but I guess I should check again to make sure this is predictable and
> consistent.
> 

I looked at how the environment variables get loaded into the form and I see that we call this method from RemoteCmdSubSystem:

	public IRemoteSystemEnvVar[] getEnvironmentVariableList() {
		IPropertySet environmentVariables = getEnvironmentVariables();
		String[] names = environmentVariables.getPropertyKeys();
		IRemoteSystemEnvVar[] result = new IRemoteSystemEnvVar[names.length];
		for (int i = 0; i < names.length; i++) {
			String name = names[i];
			String value = environmentVariables.getPropertyValue(name);
			IRemoteSystemEnvVar v = new RemoteSystemEnvVar();
			v.setName(name);
			v.setValue(value);
			result[i] = v;
		}
		return result;
	}

Because the order is determined by the order of the names returned in environmentVariables.getPropertyKeys() and we use the same method to get the keys in areEnvironmentVariables() I think the current method is okay.
Comment 17 David McKnight CLA 2008-11-10 15:15:04 EST
Since we have bug 254548 for the subsystem property page and keys should not be sorted when checking the environment variables I'm going to mark this as fixed.
Comment 18 Martin Oberhuber CLA 2008-11-12 13:21:56 EST
Fix involved an API addition:
protected boolean ServiceElement#_childChanged;