Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » scout » Problems with Luna Nightly Runtime and ListBox
Problems with Luna Nightly Runtime and ListBox [message #1124335] Thu, 03 October 2013 08:40 Go to next message
Urs Beeli is currently offline Urs Beeli
Messages: 302
Registered: October 2012
Location: Bern, Switzerland
Senior Member
Yesterday I changed my target file from Kepler RC1 to Luna Nightly because I wanted to test a bug that was fixed in Luna (background.disabled property in SWT look and feel).

This made my application throw various exceptions in connection with AbstractListBox and AbstractTreeBox.

In my forms I have various Fields extending either AbstractListBox<Long> and AbstractTreeBox<Long>. On some of them I have defined the following method to sort the entries:

@Override
protected void execFilterLookupResult(LookupCall call, List<LookupRow> result) throws ProcessingException {
  java.util.Collections.sort(result, new LookupRowComparator(LookupRowComparator.MODE_KEY));
}


And LookupRowComparator roughly looks as follows:
  @Override
  public int compare(LookupRow object1, LookupRow object2) {
    if (object1 == null) return -1;
    if (object2 == null) return 1;
    if (mode == MODE_TEXT) {
      return object1.getText().compareTo(object2.getText());
    }
    else { // mode == MODE_KEY
      return ((Long) object1.getKey()).compareTo((Long) object2.getKey());
    }
  }


When opening this form, I now suddenly get the following exception:
!ENTRY org.eclipse.scout.rt.client 4 0 2013-10-03 14:35:16.387
!MESSAGE org.eclipse.scout.rt.client.services.common.exceptionhandler.internal.InternalClientExceptionHandlerService.differentiatedLog(InternalClientExceptionHandlerService.java:116) ProcessingException: ProcessingStatus[ERROR code=0 TabbedForm / Unexpected java.lang.ClassCastException: java.math.BigDecimal incompatible with java.lang.Long]
!STACK 0
ProcessingException[ProcessingStatus[ERROR code=0 TabbedForm / Unexpected java.lang.ClassCastException: java.math.BigDecimal incompatible with java.lang.Long]]
	at org.eclipse.scout.rt.client.ui.form.FormUtility$InitFieldVisitor.visitField(FormUtility.java:170)
	at org.eclipse.scout.rt.client.ui.form.fields.listbox.AbstractListBox.visitFields(AbstractListBox.java:888)
	at org.eclipse.scout.rt.client.ui.form.fields.AbstractCompositeField.visitFields(AbstractCompositeField.java:268)
	at org.eclipse.scout.rt.client.ui.form.fields.AbstractCompositeField.visitFields(AbstractCompositeField.java:268)
	at org.eclipse.scout.rt.client.ui.form.fields.AbstractCompositeField.visitFields(AbstractCompositeField.java:268)
	at org.eclipse.scout.rt.client.ui.form.fields.AbstractCompositeField.visitFields(AbstractCompositeField.java:268)
	at org.eclipse.scout.rt.client.ui.form.AbstractForm.visitFields(AbstractForm.java:1002)
	at org.eclipse.scout.rt.client.ui.form.FormUtility.initFormFields(FormUtility.java:77)
	at org.eclipse.scout.rt.client.ui.form.AbstractForm.initForm(AbstractForm.java:1179)
	at org.eclipse.scout.rt.client.ui.form.AbstractForm.startInternal(AbstractForm.java:685)
	at org.eclipse.minicrm.client.ui.forms.TabbedForm.startDisplay(TabbedForm.java:303)
	at org.eclipse.minicrm.client.ui.desktop.Desktop$TabbedFormTool.execAction(Desktop.java:1279)
	at org.eclipse.scout.rt.client.ui.action.AbstractAction.doAction(AbstractAction.java:292)
	at org.eclipse.scout.rt.client.ui.action.AbstractAction$P_UIFacade.fireActionFromUI(AbstractAction.java:629)
	at org.eclipse.minicrm.ui.swt.application.CoolbarButton$1.run(CoolbarButton.java:175)
	at org.eclipse.scout.rt.ui.swt.concurrency.SwtScoutSynchronizer$1.runVoid(SwtScoutSynchronizer.java:60)
	at org.eclipse.scout.rt.client.ClientJob.runStatus(ClientJob.java:189)
	at org.eclipse.scout.rt.client.ClientJob.runTransactionWrapper(ClientJob.java:172)
	at org.eclipse.scout.rt.client.ClientJob.run(ClientJob.java:159)
	at org.eclipse.core.internal.jobs.Worker.run(Worker.java:54)
Caused by: java.lang.ClassCastException: java.math.BigDecimal incompatible with java.lang.Long
	at org.eclipse.minicrm.client.utils.LookupRowComparator.compare(LookupRowComparator.java:106)
	at org.eclipse.minicrm.client.utils.LookupRowComparator.compare(LookupRowComparator.java:1)
	at java.util.Arrays.mergeSort(Arrays.java:2874)
	at java.util.Arrays.mergeSort(Arrays.java:2886)
	at java.util.Arrays.mergeSort(Arrays.java:2886)
	at java.util.Arrays.sort(Arrays.java:3251)
	at java.util.Arrays.sort(Arrays.java:3269)
	at java.util.Collections.sort(Collections.java:1961)
	at org.eclipse.minicrm.client.ui.forms.TabbedForm$MainBox$MainGroupBox$TabBox$Sandbox4Box$ListBoxField.execFilterLookupResult(TabbedForm.java:2624)
	at org.eclipse.scout.rt.client.ui.form.fields.listbox.AbstractListBox.filterLookupResult(AbstractListBox.java:501)
	at org.eclipse.scout.rt.client.ui.form.fields.listbox.AbstractListBox.execLoadTableData(AbstractListBox.java:183)
	at org.eclipse.scout.rt.client.ui.form.fields.listbox.AbstractListBox.execPopulateTable(AbstractListBox.java:217)
	at org.eclipse.scout.rt.client.ui.form.fields.listbox.AbstractListBox.loadListBoxData(AbstractListBox.java:474)
	at org.eclipse.scout.rt.client.ui.form.fields.listbox.AbstractListBox.initFieldInternal(AbstractListBox.java:357)
	at org.eclipse.scout.rt.client.ui.form.fields.AbstractFormField.initField(AbstractFormField.java:830)
	at org.eclipse.scout.rt.client.ui.form.FormUtility$InitFieldVisitor.visitField(FormUtility.java:161)
	... 19 more


The problem seems to be the following line in my comparator:
      return ((Long) object1.getKey()).compareTo((Long) object2.getKey());


Changing my field definitions to AbstractListBox<BigDecimal> and my comparator to:
      return ((BigDecimal) object1.getKey()).compareTo((BigDecimal) object2.getKey());

solves the problem, but is not really what I want to do...

Similarly, on those forms where I use AbstractListBox<Long> without the execFilterLookupResult() call, I get the following exeception the moment I tick a checkbox for one of the entries:
!ENTRY org.eclipse.scout.rt.client 4 0 2013-10-03 14:38:43.325
!MESSAGE org.eclipse.scout.rt.client.ui.basic.tree.AbstractTree.fireTreeEventInternal(AbstractTree.java:2180) fire TreeEvent["P_InternalTreeNode[Deutschland]" TYPE_NODES_UPDATED]
!STACK 0
java.lang.ArrayStoreException
	at org.eclipse.scout.rt.client.ui.form.fields.treebox.AbstractTreeBox.syncTreeToValue(AbstractTreeBox.java:953)
	at org.eclipse.scout.rt.client.ui.form.fields.treebox.AbstractTreeBox.access$2(AbstractTreeBox.java:935)
	at org.eclipse.scout.rt.client.ui.form.fields.treebox.AbstractTreeBox$1.treeChanged(AbstractTreeBox.java:312)
	at org.eclipse.scout.rt.client.ui.basic.tree.AbstractTree.fireTreeEventInternal(AbstractTree.java:2177)
	at org.eclipse.scout.rt.client.ui.basic.tree.AbstractTree.fireNodesUpdated(AbstractTree.java:1957)
	at org.eclipse.scout.rt.client.ui.basic.tree.AbstractTree.setNodeChecked(AbstractTree.java:1097)
	at org.eclipse.scout.rt.client.ui.basic.tree.AbstractTreeNode.setChecked(AbstractTreeNode.java:401)
	at org.eclipse.scout.rt.client.ui.basic.tree.AbstractTree.interceptNodeClickSingleObserver(AbstractTree.java:2071)
	at org.eclipse.scout.rt.client.ui.basic.tree.AbstractTree.fireNodeClick(AbstractTree.java:2057)
	at org.eclipse.scout.rt.client.ui.basic.tree.AbstractTree.access$2(AbstractTree.java:2054)
	at org.eclipse.scout.rt.client.ui.basic.tree.AbstractTree$P_UIFacade.fireNodeClickFromUI(AbstractTree.java:2623)
	at org.eclipse.scout.rt.ui.swt.basic.tree.SwtScoutTree$5.run(SwtScoutTree.java:475)
	at org.eclipse.scout.rt.ui.swt.concurrency.SwtScoutSynchronizer$1.runVoid(SwtScoutSynchronizer.java:60)
	at org.eclipse.scout.rt.client.ClientJob.runStatus(ClientJob.java:189)
	at org.eclipse.scout.rt.client.ClientJob.runTransactionWrapper(ClientJob.java:172)
	at org.eclipse.scout.rt.client.ClientJob.run(ClientJob.java:159)
	at org.eclipse.core.internal.jobs.Worker.run(Worker.java:54)


Again, changing the field to AbstractListBox<BigDecimal> solves the problem, but again, I don't really feel like changing the types of all my ListBox fields.

Just a wild guess: Could this have anything to do with the changes described in this thread: http://www.eclipse.org/forums/index.php/t/523968/ ?
Re: Problems with Luna Nightly Runtime and ListBox [message #1124347 is a reply to message #1124335] Thu, 03 October 2013 08:55 Go to previous messageGo to next message
Ken Lee is currently offline Ken Lee
Messages: 96
Registered: March 2012
Member
Urs Beeli wrote on Thu, 03 October 2013 08:40
Just a wild guess: Could this have anything to do with the changes described in this thread: http://www.eclipse.org/forums/index.php/t/523968/ ?


Hi Urs,

I also think that this is related to bug 394984. Can you follow the optional migration guide in comment 4 and tell us if the exception still occurs?

Cheers,

Ken
Re: Problems with Luna Nightly Runtime and ListBox [message #1130022 is a reply to message #1124347] Wed, 09 October 2013 02:46 Go to previous messageGo to next message
Urs Beeli is currently offline Urs Beeli
Messages: 302
Registered: October 2012
Location: Bern, Switzerland
Senior Member
Ken Lee wrote on Thu, 03 October 2013 14:55
I also think that this is related to bug 394984.


That is the bug that relates to the thread I linked to, so it seems that my assumption was correct Smile

Ken Lee wrote on Thu, 03 October 2013 14:55
Can you follow the optional migration guide in comment 4 and tell us if the exception still occurs?


Defining DerbySqlLegacyStyle and DerbySqlLegacyService and then using DerbySqlLegacyService instead of AbstractDerbySqlService solves my problem.

However, that seems to mean that if the "new" method of column type mapping in tables is used, it is no longer possible to use fields that extend AbstractListBox<Long> and AbstractTreeBox<Long> (or any other type other than BigDecimal). Is this price worth paying for what is gained? Or is that just a bug in your change that needs to be addressed?
Re: Problems with Luna Nightly Runtime and ListBox [message #1130312 is a reply to message #1130022] Wed, 09 October 2013 08:26 Go to previous messageGo to next message
Ken Lee is currently offline Ken Lee
Messages: 96
Registered: March 2012
Member
Urs Beeli wrote on Wed, 09 October 2013 02:46
Is this price worth paying for what is gained? Or is that just a bug in your change that needs to be addressed?


Hi Urs,

I'm not quite sure what you are exactly targeting with the above quotation. Do you mean that the migration process to use the legacy SQL style is too complex?

Technically speaking, I think it makes sense to return a BigDecimal Java data type whenever a NUMERIC or DECIMAL type is read from the JDBC driver. In the old days (using legacy style) you could end up having Long AND Double data types mixed up together so that your LookupRowComparator would also fail in that case.

A Long Java data type will still be returned in case the JDBC type is (see AbstractSqlStyle.readBind()):

// Long
case Types.BIT:
case Types.BIGINT:
case Types.SMALLINT:
case Types.INTEGER:
case Types.TINYINT: {
  o = new Long(rs.getLong(jdbcBindIndex));
  break;
}


I guess that you are using a DB that doesn't support explicit integer types directly. Instead it uses something like NUMERIC(10,0) to define an integer type-like column (e.g. for a primary key).
With the legacy style you will always get a Long data type back since the number stored in that column will always have a scale equals to 0. With the latest implementation a BigDecimal is returned which is a bit of an overkill but it would be perfectly applicable if the column was defined as NUMERIC(10,5).

We had several Scout projects that encountered the problem of having mixed up data types in a single column independently and simultaneously. So we decided to standardize to conversion to a certain Java data type which corresponds to the Java data type read from the JDBC driver.
Re: Problems with Luna Nightly Runtime and ListBox [message #1131048 is a reply to message #1130312] Thu, 10 October 2013 02:16 Go to previous messageGo to next message
Urs Beeli is currently offline Urs Beeli
Messages: 302
Registered: October 2012
Location: Bern, Switzerland
Senior Member
Ken Lee wrote on Wed, 09 October 2013 14:26
I'm not quite sure what you are exactly targeting with the above quotation. Do you mean that the migration process to use the legacy SQL style is too complex?


No, the migration process was easy enough to follow.

Ken Lee wrote on Wed, 09 October 2013 14:26
I guess that you are using a DB that doesn't support explicit integer types directly. Instead it uses something like NUMERIC(10,0) to define an integer type-like column (e.g. for a primary key).


In my playground application I'm using a derby DB (it's based on the minicrm tutorial). I use that application to "try out" new features, so I don't have to do that in our production code (which uses Hibernate instead of Scout's SQL services, so it's not an issue there).

My concern was that with the new mapping method, it was impossible to use AbstractListBox<Long>. I didn't realise that this limitation only applies for databases with the limitation I quote above, so I thought it was a general problem
that you could either have "good mapping" or the ability to use AbstractListBox<Long> but not both.

If this is indeed only happening because I'm using derby, and will work with "proper" databases that have explicit numerical types (though I'm not familiar enough with other database engines to know which ones do; I believe DB2 on Mainframe also only has "DECIMAL(x,x)") then I guess my point is less relevant.

Ken Lee wrote on Wed, 09 October 2013 14:26
We had several Scout projects that encountered the problem of having mixed up data types in a single column independently and simultaneously. So we decided to standardize to conversion to a certain Java data type which corresponds to the Java data type read from the JDBC driver.


Oh, I understand the reason behind the change (I loosely followed that thread), I just didn't realise it would affect anything else than tables and was surprised that it broke existing code in cases where no mixed datatypes were used.
Re: Problems with Luna Nightly Runtime and ListBox [message #1131077 is a reply to message #1131048] Thu, 10 October 2013 02:58 Go to previous messageGo to next message
Ken Lee is currently offline Ken Lee
Messages: 96
Registered: March 2012
Member
Urs Beeli wrote on Thu, 10 October 2013 02:16
No, the migration process was easy enough to follow.


Ok, good to know because we also think that the migration should be easy enough.

Urs Beeli
In my playground application I'm using a derby DB (it's based on the minicrm tutorial).

As far as I remember, Derby DB returns numeric or decimal JDBC data types. Therefore (in the "old days"), you would get a Long or a Double data type in Java as shown in the other forum thread.

Urs Beeli
I didn't realise that this limitation only applies for databases with the limitation I quote above, so I thought it was a general problem
that you could either have "good mapping" or the ability to use AbstractListBox<Long> but not both.


Yes, the change is only limited to DB queries where numerical or decimal values are involved. If it was a general problem, we would definitely have to create a follow bug Smile

Urs Beeli
If this is indeed only happening because I'm using derby, and will work with "proper" databases that have explicit numerical types (though I'm not familiar enough with other database engines to know which ones do; I believe DB2 on Mainframe also only has "DECIMAL(x,x)") then I guess my point is less relevant.


The "standard" operations like filling up the formdata with the result of the DB or loading data into a Scout table are not affected by the change because they use the TypeCastUtility in the background to convert the BigDecimal into a Long or Double value.
The problem arises however, if you load the table result into a Java Object array and do some manual sorting. With the old conversion, you might expect something of type Long or Double but you will get a BigDecimal data type now. This is exactly what happened in your example above.

Urs Beeli

Oh, I understand the reason behind the change (I loosely followed that thread), I just didn't realise it would affect anything else than tables and was surprised that it broke existing code in cases where no mixed datatypes were used.


In contrast to your example, in the other Scout projects they were expecting pure Double data types but finally received a mix of Long and Double values. That's the reason for the "standardization" of the conversion.

I'm glad that we could tackle this problematic already at an early stage. I'm sure that the same question will arise again if more projects use Scout 3.10.
Re: Problems with Luna Nightly Runtime and ListBox [message #1131216 is a reply to message #1131077] Thu, 10 October 2013 05:59 Go to previous message
Jeremie Bresson is currently offline Jeremie Bresson
Messages: 529
Registered: October 2011
Senior Member
Ken Lee wrote on Thu, 10 October 2013 08:58
The problem arises however, if you load the table result into a Java Object array and do some manual sorting. With the old conversion, you might expect something of type Long or Double but you will get a BigDecimal data type now. This is exactly what happened in your example above.


Form what I understood; we can summarize it like this:

Previously the SQL Layer was taking care of the conversion NUMERIC (SQL) --> Long (Java). Today the conversion is: NUMERIC --> BigDecimal.
From what I understood from the other forum thread, this is necessary.

* * *

I think that AbstractSqlLookupService is a legitimate use case where you might want to control the type of the key:

You know where the LookupService is used (by wich LookupCall). With the old implementation, you used this LookupCall in a SmartField<Long> or TreeBox<Long> field.
This is a very representative use case. From what I understood from Urs Beeli: in a lot of cases you know that you have a number without decimal part in your NUMERIC column and for those cases the old Long type was easier to work with than the new BigDecimal type.

Now my proposal:
When we write the query of in the SqlLookupService, we know the type of the Key we want to have. What about adding a getConfiguredKeyClass() in the AbstractSqlLookupService? In the execLoadLookupRows(..) we add an additional step in the default implementation: If keyClass == null (default returned value) the step does nothing. If not null (Long.class for example), for each rows of the result set we do the casting of the key with the TypeCastUtility (the key of the LookupRow is Column 0 in the Object[][] data array). This is near from what the previous SQL was doing.

Previous Topic:Question to Bug 414535
Next Topic:Set size of a form
Goto Forum:
  


Current Time: Sat Apr 19 21:51:05 EDT 2014

Powered by FUDForum. Page generated in 0.05244 seconds