Link to home
Start Free TrialLog in
Avatar of cc042297
cc042297

asked on

Assigned property losts it's value without touching it

Hello,

I am using Eclipse  3.4.2 Build  M20090211-1700 for an SWT project.

As the title sais I have a property ("owner") loosing it's value without  ever touching it.
after the  initial assignment, which  takes place in the constructor of SomeItem. It holds a reference to it's owner, and the owner feeds itself (as "this") to the constructor when creating  it's items.

 The problem occures when  trying to call  someItemInstance.doSomething() form a third class.  It fails because owner is null.

How on Earth  this can be when it is absolutely sure that "owner"  is never again touched  after it's initializaton in the constructor?

Any help greatly appreciated! :)


class SomeItem extends SomeSerializableClass{
 
   private ItemOwner owner;
 
   public SomeItem (ItemOwner owner){
      super(...);
      this.owner = owner;
   }
 
   public void doSomething(){
      owner;doSomething();
   }
}

Open in new window

Avatar of CEHJ
CEHJ
Flag of United Kingdom of Great Britain and Northern Ireland image

Has it been *de*serialized? If so it won't work correctly. Serialization depends on a no-arg constructor and your one-arg one won't be called
and is that *all* the code?

Avatar of cc042297
cc042297

ASKER

CEHJ:

I am sorry, I got it wrong: SomeItem extends, from  a class extending from SWT Canvas.

objects:

As you can see owner is a private field, not accessible from outside, and the class is almost this simple . I can guarantee that only assignment "owner" gets is in the constructor. But seee it for yourself. :)) "owner" is  "private DBTree tree"
public class DBTreeColumn extends DBControl{
	private DBTree tree;
	public DBTreeColumn parentColumn;
	public DBTreeColumn childColumn;
	public TreeColumn treeColumn;
	public DBDataSet dataSet;
	//public DBField field;
	public int style;
	
	public DBTreeColumn(DBTree tree, DBTreeColumn parentColumn, DBField field, int style) {
		super(tree, field, 0); 
		
		this.tree = tree;
		this.parentColumn = parentColumn;
		if (parentColumn != null)
			parentColumn.childColumn = this;
 
		treeColumn = new TreeColumn(tree.treeWidget, field.fieldEditorStyle);
		treeColumn.setText(field.caption);
		treeColumn.setWidth(field.displayWith);
 
		tree.columns.add(this);
 
		// this is a special case, when the DBcontrol is not displaying the data itself,
		// but tells it's owner to do it -->the control itself must not display at all
		setVisible(false);
 
		//  Establish data connection
		setField(field);
		
		
	}
 
	public void setField(DBField field) {
		// Unregister control from the current DataSet 
		if (this.field != null) {
			if (dataSet.dataControls.contains(this))
				dataSet.dataControls.remove(this);
		}
			
		this.field = field;
		dataSet = field.dataSet;
		
		// Register control at the new DataSet 
		if (!dataSet.dataControls.contains(this))
			dataSet.dataControls.add(this);
		
		treeColumn.setData(field);
		
	}
 
	
	@Override
	public void refresh(){ 
		tree.refresh();
		
	}
 
	@Override
	public void saveChanges() {
		// TODO Auto-generated method stub
		
	}
}
 
the only place the constructor is called:
class ItemOwner {
...
column = new DBTreeColumn(this, parentColumn, field, style );

Open in new window

and how have you tested that it is null?

>>As you can see owner is a private field,

Where is 'owner' in what you just posted?
CEHJ:

"owner" is  "          =  "private DBTree tree"
"doSometthing"    =  public void refresh()    (see its declaration in snippet)


objects:

java.lang.NullPointerException
      at db.DBTreeColumn.refresh(DBTreeColumn.java:62)


Tried to "protect" you guys  from the original code, but  loks like it is not possible to pin down the problem without some of it. Feel free to ask what you need! :))


 Tested with a breakpoint too.


 
public abstract class DBControl extends Canvas {
	protected DBField field;
	
	public abstract void refresh();
	public abstract void saveChanges();
...

Open in new window

CEHJ:

"doSometthing"    =  public void refresh()    (see its  ORIGINAL declaration in snippet)
that stack trace does not match the code you posted above
which is line 62?

make sure you are using the lastest class file and not an old version.

Ooops, sorry. Deleted a comment block after pasting this here. Here it is again :)
package db;
 
import org.eclipse.swt.widgets.TreeColumn;
 
public class DBTreeColumn extends DBControl{
	private DBTree tree;
	public DBTreeColumn parentColumn;
	public DBTreeColumn childColumn;
	public TreeColumn treeColumn;
	public DBDataSet dataSet;
	//public DBField field;
	public int style;
	
	public DBTreeColumn(DBTree tree, DBTreeColumn parentColumn, DBField field, int style) {
		super(tree, field, 0); 
		
		this.tree = tree;
		this.parentColumn = parentColumn;
		if (parentColumn != null)
			parentColumn.childColumn = this;
 
		treeColumn = new TreeColumn(tree.treeWidget, field.fieldEditorStyle);
		treeColumn.setText(field.caption);
		treeColumn.setWidth(field.displayWith);
 
		tree.columns.add(this);
 
		// this is a special case, when the DBcontrol is not displaying the data itself,
		// but tells it's owner to do it -->the control itself must not display at all
		setVisible(false);
 
		//  Establish data connection
		setField(field);
		
		
	}
 
	public void setField(DBField field) {
		// Unregister control from the current DataSet 
		if (this.field != null) {
			if (dataSet.dataControls.contains(this))
				dataSet.dataControls.remove(this);
		}
			
		this.field = field;
		dataSet = field.dataSet;
		
		// Register control at the new DataSet 
		if (!dataSet.dataControls.contains(this))
			dataSet.dataControls.add(this);
		
		treeColumn.setData(field);
		
	}
 
/*	private DBTree getTree() {
		return tree;
	}
*/	
	@Override
	public void refresh(){ 
		tree.refresh();
		
	}
 
	@Override
	public void saveChanges() {
		// TODO Auto-generated method stub
		
	}
}

Open in new window

add a test in refresh() and the ctor, something like

System.out.println("true is null "+(tree==null));
Please post the *full* stack trace
tree is null
java.lang.NullPointerException
      at db.DBTreeColumn.refresh(DBTreeColumn.java:65)
      at db.DBDataSet.scrolled(DBDataSet.java:104)
      at db.DBDataSet.setActItem(DBDataSet.java:147)
      at gui.AdminSettings$6.widgetSelected(AdminSettings.java:158)
      at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:228)
      at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
      at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1003)
      at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3823)
      at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3422)
      at gui.EcgDraw.<init>(EcgDraw.java:100)
      at gui.EcgDraw.main(EcgDraw.java:116)
did u add it to the ctor as well?

objects:

yes, but at the end of the ctor tree is not null.
 
SOLUTION
Avatar of CEHJ
CEHJ
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I think I found the source of the problem,

Here is a place where it occures::

I have a class (Activities) which has a DBField propety (activityName).
.
The problem originates form the way  the DBField propety  is assigned: it recieves a SUBLASS of DBField as a value,  "activityName" is not assigned during the creation of "Activities", but sometime later by calling createFields().  When I try to use "activityName" AFTER createFields() is run, it turns out to be null. As any property assigned the same way.    

The problem could be they way subclassing is done, or  sublassing itself. I am quite new  to java, so I may be crosspasing some basic principles here.

If I do not find a way to implement what I have tried here by subclassing, I wil have to throw lots of work out  the window, and I will definetely will run out of time. Please help me to get this streight if you can. :)))

.


public class Activities extends DBDataSet {
	public RangeTypes rangeTypes;
	
 
	// Fields
	public DBField activityName; 
 
	
	public Activities() {
 
 
		items =  new ArrayList<Activity>();
		setData(new DBData(items));
	}
	
	public ArrayList<Activity> getItems() {
		return (ArrayList<Activity>) items;
	}
 
 
	public Activity getActItem() {
		return (Activity) actItem;
	}
 
	@Override
	public void createFields() {
		// Fields
		activityName  = new DBField(this, "Tevékenység"   , 100, true, DBDataType.STRING, SWT.LEFT, null){
			@Override
			public String getAsString(){return getActItem().name;}
			@Override
			public void setAsString(String value){edit(); getActItem().name = value; post();}
		}; 
		
	}
	
	
	
}

Open in new window

not sure I follow you, its not being assigned a subclass that I can see. Not that that would make any difference.

could be swt changing the value using reflection, certainly possible.

I do not know what  " SWT reflection" is, but the more important question is how to prevent it? Any idea?
if you can prduce a *small* example that I can run to reproduce the problem then I can have a look at it for you

Wow, I think I have solved it,  Do not have the time now, but I will come back to clarify the situation and close the thread (+award the points)  when it is certain.
:-)