Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » scout » Problems refreshing a form-on-a-page
Problems refreshing a form-on-a-page [message #1003535] Mon, 21 January 2013 13:12 Go to next message
Urs Beeli is currently offline Urs BeeliFriend
Messages: 346
Registered: October 2012
Location: Bern, Switzerland
Senior Member
In my scout application I have a (read-only) form that is being displayed on an AbstractPage as a view.

In my FormPage class I have the following code:

public class TabbedFormPage extends AbstractPage {
  private TabbedForm form = null;

  @Override
  protected void execPageActivated() throws ProcessingException {
    form = new TabbedForm();
    form.setDisplayHint(IForm.DISPLAY_HINT_VIEW);
    form.setDisplayViewId(IForm.VIEW_ID_PAGE_DETAIL);
    form.setEnabledGranted(false);
    form.startDisplay();
  }

  @Override
  protected void execPageDeactivated() throws ProcessingException {
    if (form != null) {
      form.doClose();
      form = null;
    }
  }
}


In my TabbedForm class I have the following code (excerpt only):
  public void startDisplay() throws ProcessingException {
    startInternal(new DisplayHandler());
  }

  public class DisplayHandler extends AbstractFormHandler {
    @Override
    public void execLoad() throws ProcessingException {
      ITabbedProcessService service = SERVICES.getService(ITabbedProcessService.class);
      TabbedFormData formData = new TabbedFormData();
      exportFormData(formData);
      formData = service.load(formData);
      importFormData(formData);
      setEnabledPermission(new ReadTabbedPermission());
    }
  }


This works, retrieving my data from the server and displaying it in the form instead of a table.

Now, there are circumstances in which the data in the DB can change (e.g. through modification by other users) and I want the data in the table to be updated. With a table page, I can press F5 to do this, so I wanted to mimick this behaviour. In order to do this, I made the following changes:

In TabbedFormPage I added
  @Override
  protected void execPageDataLoaded() throws ProcessingException {
    if (form != null) {
      form.refreshForm();
    }
  }


And in TabbedForm I refactored the code that retrieves and displays the data out of the DisplayHandler into refreshForm:
  public void refreshForm() throws ProcessingException {
    ITabbedProcessService service = SERVICES.getService(ITabbedProcessService.class);
    TabbedFormData formData = new TabbedFormData();
    exportFormData(formData);
    formData = service.load(formData);
    importFormData(formData);
    setEnabledPermission(new ReadTabbedPermission());
  }

  public class DisplayHandler extends AbstractFormHandler {
    @Override
    public void execLoad() throws ProcessingException {
      refreshForm();
    }
  }


This works well when displaying the form initially, the data is retrieved from the server and displayed in the form.

However, when I press F5 and the line
formData = service.load(formData)

is called, the server throws the following exception:

!ENTRY org.eclipse.scout.rt.server 4 0 2013-01-21 14:00:21.317
!MESSAGE org.eclipse.scout.rt.server.ServiceTunnelServlet.doPost(ServiceTunnelServlet.java:322) Session=8emgq3ix80g2lntr7bgx6vn5, Client=u208490@127.0.0.1/127.0.0.1
!STACK 0
java.lang.SecurityException: value is of inconsistent type; potential value corruption attack
at org.eclipse.scout.rt.shared.data.form.fields.AbstractValueFieldData.readObject(AbstractValueFieldData.java:59)
at sun.reflect.GeneratedMethodAccessor11.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
at java.lang.reflect.Method.invoke(Method.java:611)
at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1044)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1866)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1770)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1346)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:365)
at java.util.HashMap.readObject(HashMap.java:875)
at sun.reflect.GeneratedMethodAccessor10.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
at java.lang.reflect.Method.invoke(Method.java:611)
at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1044)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1866)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1770)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1346)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1964)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1888)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1770)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1346)
at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1684)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1340)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1964)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1888)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1770)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1346)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:365)
at org.eclipse.scout.rt.shared.servicetunnel.DefaultServiceTunnelContentHandler.getData(DefaultServiceTunnelContentHandler.java:391)
at org.eclipse.scout.rt.shared.servicetunnel.DefaultServiceTunnelContentHandler.read(DefaultServiceTunnelContentHandler.java:373)
at org.eclipse.scout.rt.shared.servicetunnel.DefaultServiceTunnelContentHandler.readRequest(DefaultServiceTunnelContentHandler.java:319)
at org.eclipse.scout.rt.server.ServiceTunnelServlet.deserializeInput(ServiceTunnelServlet.java:328)
at org.eclipse.scout.rt.server.ServiceTunnelServlet.doPost(ServiceTunnelServlet.java:280)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:755)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
at org.eclipse.scout.http.servletfilter.HttpServletEx.access$0(HttpServletEx.java:1)
at org.eclipse.scout.http.servletfilter.HttpServletEx$1.service(HttpServletEx.java:38)
at org.eclipse.scout.http.servletfilter.internal.FilterChainImpl.doFilter(FilterChainImpl.java:44)
at org.eclipse.scout.http.servletfilter.helper.HttpAuthJaasFilter.doFilter(HttpAuthJaasFilter.java:62)
at org.eclipse.scout.http.servletfilter.internal.FilterChainImpl.doFilter(FilterChainImpl.java:41)
at org.eclipse.scout.http.servletfilter.helper.DevelopmentAuthFilter.doFilter(DevelopmentAuthFilter.java:61)
at org.eclipse.scout.http.servletfilter.internal.FilterChainImpl.doFilter(FilterChainImpl.java:41)
at org.eclipse.scout.http.servletfilter.security.AbstractChainableSecurityFilter.doFilter(AbstractChainableSecurityFilter.java:103)
at org.eclipse.scout.http.servletfilter.internal.FilterChainImpl.doFilter(FilterChainImpl.java:41)
at org.eclipse.scout.http.servletfilter.security.AbstractChainableSecurityFilter.doFilterInternal(AbstractChainableSecurityFilter.java:220)
at org.eclipse.scout.http.servletfilter.security.AbstractChainableSecurityFilter.access$0(AbstractChainableSecurityFilter.java:219)
at org.eclipse.scout.http.servletfilter.security.AbstractChainableSecurityFilter$1.run(AbstractChainableSecurityFilter.java:157)
at java.security.AccessController.doPrivileged(AccessController.java:284)
at javax.security.auth.Subject.doAs(Subject.java:573)
at org.eclipse.scout.http.servletfilter.security.AbstractChainableSecurityFilter.doFilter(AbstractChainableSecurityFilter.java:149)
at org.eclipse.scout.http.servletfilter.internal.FilterChainImpl.doFilter(FilterChainImpl.java:41)
at org.eclipse.scout.http.servletfilter.security.AbstractChainableSecurityFilter.doFilter(AbstractChainableSecurityFilter.java:103)
at org.eclipse.scout.http.servletfilter.internal.FilterChainImpl.doFilter(FilterChainImpl.java:41)
at org.eclipse.scout.http.servletfilter.security.AbstractChainableSecurityFilter.doFilter(AbstractChainableSecurityFilter.java:103)
at org.eclipse.scout.http.servletfilter.internal.FilterChainImpl.doFilter(FilterChainImpl.java:41)
at org.eclipse.scout.http.servletfilter.ServletFilterDelegate.delegateServiceMethod(ServletFilterDelegate.java:57)
at org.eclipse.scout.http.servletfilter.HttpServletEx.service(HttpServletEx.java:35)
at org.eclipse.equinox.http.registry.internal.ServletManager$ServletWrapper.service(ServletManager.java:180)
at org.eclipse.equinox.http.servlet.internal.ServletRegistration.service(ServletRegistration.java:61)
at org.eclipse.equinox.http.servlet.internal.ProxyServlet.processAlias(ProxyServlet.java:128)
at org.eclipse.equinox.http.servlet.internal.ProxyServlet.service(ProxyServlet.java:60)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
at org.eclipse.equinox.http.jetty.internal.HttpServerManager$InternalHttpServiceServlet.service(HttpServerManager.java:384)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:598)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:486)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1065)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:413)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:192)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:999)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:111)
at org.eclipse.jetty.server.Server.handle(Server.java:350)
at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:454)
at org.eclipse.jetty.server.AbstractHttpConnection.content(AbstractHttpConnection.java:900)
at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.content(AbstractHttpConnection.java:954)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:851)
at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:235)
at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:77)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:606)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:46)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:603)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:538)
at java.lang.Thread.run(Thread.java:736)

Obviously I'm doing something I'm not supposed to do Shocked , can anyone tell me what exactly it is, that I did wrong or how I can correctly refresh the form data of an already open and populated form (I'm aware that this would discard any changes made since the initial opening, but since it is a read-only form, I don't mind)?
Re: Problems refreshing a form-on-a-page [message #1004042 is a reply to message #1003535] Tue, 22 January 2013 13:42 Go to previous messageGo to next message
Jeremie Bresson is currently offline Jeremie BressonFriend
Messages: 818
Registered: October 2011
Senior Member
From what I have seen:

java.lang.SecurityException: value is of inconsistent type; potential value corruption attack

occures when the Java type of the Value in a form do not match the type registered in a FormData.

It is easy to produce a such error with a lookup call returning a lookup row with the wrong key type.
Because internally every value is a Object (Generic -> Type erasure), some stuff works at runtime...
But there is an additional security check when the value is put to a FormData.

Are you sure your your FormData are up to date?
Have you a smartfield in your form?

You can also try to reproduce the case without the page (opening the form via a Menu).
Re: Problems refreshing a form-on-a-page [message #1004411 is a reply to message #1004042] Wed, 23 January 2013 07:24 Go to previous messageGo to next message
Urs Beeli is currently offline Urs BeeliFriend
Messages: 346
Registered: October 2012
Location: Bern, Switzerland
Senior Member
The same formData is used for the inital call to populate the form. There it works.
On a subsequent call, the exact same formData is used but the call causes the exception.

The formData is up to date and yes, I do have smart fields on the form.

I'll have to add some code to open this form in a window instead of on a page.

I've also been able to cause the exception by placing a ResetButton on the form and clicking on it.
Re: Problems refreshing a form-on-a-page [message #1005379 is a reply to message #1004411] Fri, 25 January 2013 08:07 Go to previous messageGo to next message
Jeremie Bresson is currently offline Jeremie BressonFriend
Messages: 818
Registered: October 2011
Senior Member
Are you sure that all your LookupCall (or CodeType if you use them) provide a key that have a type compatible with the type defined in the SmartField?

Can you identify when precisely it occurs? (you said when you reload or reset a form -> I assume it is when some value is set on a field)

You could also add a break point at the check and try to identify the FieldData (== the FormData element corresponding to a form field) responsible for that.

I hope this helps.
Re: Problems refreshing a form-on-a-page [message #1005746 is a reply to message #1005379] Mon, 28 January 2013 14:09 Go to previous messageGo to next message
Urs Beeli is currently offline Urs BeeliFriend
Messages: 346
Registered: October 2012
Location: Bern, Switzerland
Senior Member
Jeremie

I was going to write a quick reply but somehow ended up debugging for the last 3 hours Smile

I've been to track down the problem and I believe it is a scout bug. Maybe you can quickly confirm me analysis before I open a bug, maybe I missed something.

Anyway, I've been able to narrow down the problem to a UTCDateField on my form.

In my client code (the form) I have the following code snippet which is called from DisplayHandler.execLoad() for the inital display (then it works) and also when on the corresponding page the F5 key is used:
  public void refreshForm() throws ProcessingException {
    ITabbedProcessService service = SERVICES.getService(ITabbedProcessService.class);
    TabbedFormData formData = new TabbedFormData();
    exportFormData(formData);
    formData = service.load(formData); // server exception is thrown when executing this line
    importFormData(formData);
    setEnabledPermission(new ReadTabbedPermission());
  }


I set a breakpoint in my ProcessService.load() method but that never gets called, the exception is thrown earlier. Digging down into the server, I found out that the exception is being thrown in AbstractValueFieldData.readObject
  private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
    s.defaultReadObject();
    //verify if valueSet and the type of the value are valid and consistent
    if (!isValueSet()) {
      m_value = null;
    }
    if (m_value == null) {
      return;
    }
    if (!getHolderType().isAssignableFrom(m_value.getClass())) {
      throw new SecurityException("value is of inconsistent type; potential value corruption attack");
    }
  }


This throws an exception for TabbedFormData$UTC (the form data field for an AbstractUTCDateField on the form) on the refresh.

During the inital call, m_value is of type UTCDate and getHolderType() returns UTCDate as well.
During the refresh call, m_value is of type Date but getHolderType() still returns UTCDate. This causes the isAssignableFrom() to fail and causes the exception.

Removing the UTCDateField from the form solves this problem, I can now easily press both F5 to refresh or use the AbstractResetButton on the form.

So, I re-added the UTCDateField again did some debugging on the client side:

I stepped through the code below and after each step, inspected formData.m_fieldMap.elementData[i].value.m_value (where i is the index for the UTCDate field's data member).
    ITabbedProcessService service = SERVICES.getService(ITabbedProcessService.class);
    TabbedFormData formData = new TabbedFormData();
    exportFormData(formData);
    formData = service.load(formData);
    importFormData(formData);
    setEnabledPermission(new ReadTabbedPermission());


The result was as follows:

--- initial load ---
after new: m_value = null
after exportFormData: m_value = null (no data in the form yet)
after service.load: m_value = UTCDate(...)
after importFormData: m_value = UTCDate(...)

--- refresh ---
after new: m_value = null
after exportFormData: m_value = Date() -> there was data in the form, this seems to be the difference between the two cases

So it seems that the problem comes down to exportFormData being handled wrongly for UTCDateField when there is content already in the form.

Digging down a bit deeper, the problem occurs in:
AbstractValueField.exportFormFieldData -> v.setValue(this.getValue());
AbstractValueField.getValue -> return (T) propertySupport.getProperty(PROP_VALUE)
BasicPropertySupport.getProperty -> m_props.get(name)

--> this returns the value property. Looking a m_props.elementData[i].value, this is of type Date().

Where does this property come from?

Setting a breakpoint in AbstractVieldFalue.setValue() shows that it is called with a rawValue of type UTCDate but then on the line
validatedValue = validateValue(rawValue);
this type is converted to Date because AbstractDateField overwrites validateValueInternal() but AbstractUTCDateField does not, so AbstractDateField.validateValueInternal() is called for UTCDateFields as well:
  @Override
  protected Date validateValueInternal(Date rawValue) throws ProcessingException {
    //legacy support
    Object legacyValue = rawValue;
    if (legacyValue instanceof Number) {
      rawValue = DateUtility.convertDoubleTimeToDate((Number) legacyValue);
    }
    Date validValue = null;
    rawValue = super.validateValueInternal(rawValue);
    try {
      // apply format
      DateFormat df = getDateFormat();
      rawValue = df.parse(df.format(rawValue));   --> this line converts rawValue from UTCDate to Date!!!
    }
    catch (Throwable t) {
      // nop, take raw value
    }
    validValue = rawValue;
    return validValue;
  }


So, I believ that this is a Scout bug and that AbstractUTCDateField needs to have its own validateValueInternal method which returns a UTCDate object instead of the Date object returned by AbstractDateField.validateValueInternal.

Do you concur with this analysis? If so, I will open a bug for this issue.
Re: Problems refreshing a form-on-a-page [message #1005814 is a reply to message #1005746] Mon, 28 January 2013 20:17 Go to previous messageGo to next message
Jeremie Bresson is currently offline Jeremie BressonFriend
Messages: 818
Registered: October 2011
Senior Member
Thanks a lot for your analysis...

I put it on my TODO list. I am sorry because I do not have a lot of time these days.
Re: Problems refreshing a form-on-a-page [message #1005866 is a reply to message #1005814] Tue, 29 January 2013 06:42 Go to previous messageGo to next message
Urs Beeli is currently offline Urs BeeliFriend
Messages: 346
Registered: October 2012
Location: Bern, Switzerland
Senior Member
No worries. If you want to, I can open a bug without your confirmation, if I'm wrong, the person looking at the bug will probably tell me, too Smile
Re: Problems refreshing a form-on-a-page [message #1006374 is a reply to message #1005866] Thu, 31 January 2013 07:27 Go to previous message
Urs Beeli is currently offline Urs BeeliFriend
Messages: 346
Registered: October 2012
Location: Bern, Switzerland
Senior Member
As you are short of time and I will be gone on holidays next week, I opened Bug 399585 about this.
Previous Topic:How to switch outlines with SWT
Next Topic:Problem creating webservice Provider
Goto Forum:
  


Current Time: Sun Dec 21 05:41:43 GMT 2014

Powered by FUDForum. Page generated in 0.01895 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software