RSS 2.0
Sign In
# Saturday, 05 December 2009

Did you ever hear that double numbers may cause roundings, and that many financial institutions are very sensitive to those roundings?

Sure you did! We're also aware of this kind of problem, and we thought we've taken care of it. But things are not that simple, as you're not always know what an impact the problem can have.

To understand the context it's enough to say that we're converting (using xslt by the way) programs written in a CASE tool called Cool:GEN into java and into C#. Originally, Cool:GEN generated COBOL and C programs as deliverables. Formally, clients compare COBOL results vs java or C# results, and they want them to be as close as possible.

For one particular client it was crucial to have correct results during manipulation with numbers with 20-25 digits in total, and with 10 digits after a decimal point.

Clients are definitely right, and we've introduced generation options to control how to represent numbers in java and C# worlds; either as double or BigDecimal (in java), and decimal (in C#).

That was our first implementation. Reasonable and clean. Was it enough? - Not at all!

Client's reported that java's results (they use java and BigDecimal for every number with decimal point) are too precise, comparing to Mainframe's (MF) COBOL. This rather unusuall complain puzzles a litle, but client's confirmed that they want no more precise results than those MF produces.

The reason of the difference was in that that both C# and especially java may store much more decimal digits than is defined for the particualar result on MF. So, whenever you define a field storing 5 digits after decimal point, you're sure that exactly 5 digits will be stored. This contrasts very much with results we had in java and C#, as both multiplication and division can produce many more digits after the decimal point. The solution was to truncate(!) (not to round) the numbers to the specific precision in property setters.

So, has it resolved the problem? - No, still not!

Client's reported that now results much more better (coincide with MF, in fact) but still there are several instances when they observe differences in 9th and 10th digits after a decimal point, and again java's result are more accurate.

No astonishment this time from us but analisys of the reason of the difference. It's turned out that previous solution is partial. We're doing a final truncation but still there were intermediate results like in a/(b * c), or in a * (b/c).

For the intermediate results MF's COBOL has its, rather untrivial, formulas (and options) per each operation defining the number of digits to keep after a decimal point. After we've added similar options into the generator, several truncations've manifested in the code to adjust intermediate results. This way we've reached the same accurateness as MF has.

What have we learned (reiterated)?

  • A simple problems may have far reaching impact.
  • More precise is not always better. Client often prefers compatible rather than more accurate results.
Saturday, 05 December 2009 13:17:42 UTC  #    Comments [0] -
Tips and tricks | xslt
# Thursday, 03 December 2009

Recently we were visiting Ukraine, the capital city, and a town we've come from.

Today's Ukraine makes a twofold impression.

On the one hand it's a childhood places and relatives, an enormous pleasure of meeting university and school friends, a good surprise of meeting university chancellor who was already hoary with age when we were studying.

On the other hand it's already a very different country from what the memory draws. I must be wrong but my impression was that it's a country of traders and endless political battles. It's neither bad nor good but a point of history. Unfortunately we cannot think ourselves now living in Ukraine.

On the question where is our home now, we have the only answer it's in Israel.

Thursday, 03 December 2009 07:32:18 UTC  #    Comments [0] -

# Friday, 13 November 2009

For some reason C# lacks a decimal truncation function limiting result to a specified number of digits after a decimal point. Don't know what's the reasoning behind, but it stimulates the thoughts. Internet is plentiful with workarounds. A tipical answer is like this:

Math.Truncate(2.22977777 * 1000) / 1000; // Returns 2.229

So, we also want to provide our solution to this problem.

public static decimal Truncate(decimal value, byte decimals)
{
  decimal result = decimal.Round(value, decimals);
  int c = decimal.Compare(value, result);
  bool negative = decimal.Compare(value, 0) < 0;

  if (negative ? c <= 0 : c >= 0)
  {
    return result;
  }

  return result - new decimal(1, 0, 0, negative, decimals);
}

Definitely, if the function were implemented by the framework it were much more efficient. We assume, however, that above's the best implementation that can be done externally.

Friday, 13 November 2009 14:31:26 UTC  #    Comments [0] -
Tips and tricks
# Tuesday, 03 November 2009

A natural curiosity led us to the implementation of connection pooling in Apache Tomcat (org.apache.commons.dbcp).

And what're results do you ask?

Uneasiness... Uneasiness for all those who use it. Uneasiness due to the difference between our expectations and real implementation.

Briefly the design is following:

  • wrap every jdbc object;
  • cache prepared statements wrappers;
  • lookup prepared statement wrappers in the cache before asking original driver;
  • upon close return wrappers into the cache.

It took us a couple of minutes to see that this is very problematic design, as it does not address double close of statements properly (jdbc states that is safe to call close() over closed jdbc object). With Apache's design it's safe not to touch the object after the close() call, as it returned to the pool and possibly already given to an other client who requested it.

The correct design would be:

  • wrap every jdbc object;
  • cache original prepared statements;
  • lookup original prepared statement in the cache before asking original driver, and return wrappers;
  • detach wrapper upon close from original object, and put original object into the cache.

A bit later. We've found a confirmation of our doubts on Apache site: see "JNDI Datasource HOW-TO ", chapter "Common Problems".

Tuesday, 03 November 2009 11:20:00 UTC  #    Comments [0] -
Tips and tricks

In a twitter I've found a conversation:

michaelhkay: @fgeorges [XSLT 2.1 - Still nothing public?] Afraid not. Why don't you join the WG and help to speed things up?

I think it's a tendency.

WGs are a very different world. There people think of eternity... There a pace of time is less important than final words. But developers who're busy with their projects, and have no enough spare time to help to WGs, cannot wait for years for good specs and implementations. On the other hand good designers succeed dealing with existing technologies.

Looking into the future I see different perspectives regarding WGs. The one I think the most is that eventually WG'll run out of its enthusiasm, which I suspect happens after the second generation of members, and a technology'll go either to a museum, become a legacy but sill used one, or hopefully to a university community.

At present I'm calm about Xslt/XQuery WGs, as they're only approaching to the second generation. My fears're about C++ WG, which is on its third decade...

Tuesday, 03 November 2009 09:21:25 UTC  #    Comments [0] -

# Saturday, 10 October 2009

It's not a secret that we don't like JSF (something is very wrong with whole its design), however we have no choice but to work with it. But at times to lift hands up is only wish we have working with it.

The last pearl is with check box control: selectBooleanCheckbox. It turns out that when you disable the control on a client and assume that its value won't be databound on a server, you're wrong. Browser does not send the value as you would expect, but JSF (reference implementation at least) works like this:

private static String isChecked(String value) {
  return Boolean.toString("on".equalsIgnoreCase(value)
    || "yes".equalsIgnoreCase(value)
    || "true".equalsIgnoreCase(value));
}

where value is null, which means that JSF thinks checkbox is unchecked.

Saturday, 10 October 2009 10:06:52 UTC  #    Comments [0] -
JSF and Facelets
# Wednesday, 07 October 2009

Our experience with facelets shows that when you're designing a composition components you often want to add a level of customization. E.g. generate element with or without id, or define class/style if value is specified.

Consider for simplicity that you want to encapsulate a check box and pass several attributes to it. The first version that you will probably think of is something like this:

<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:ui="http://java.sun.com/jsf/facelets"
  xmlns:c="http://java.sun.com/jstl/core"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:ex="http://www.nesterovsky-bros.com/jsf">
  <body>
    <!--
      Attributes:
        id - an optional id;
        value - a data binding;
        class - an optional element class;
        style - an optional element inline style;
        onclick - an optional script event handler for onclick event;
        onchange - an optional script event handler for onchange event.
    -->
    <ui:component>
      <h:selectBooleanCheckbox
        id="#{id}"
        value="#{value}"
        style="#{style}"
        class="#{class}"
        onchange="#{onchange}"
        onclick="#{onclick}"/>
    </ui:component>
  </body>
</html>

Be sure, this is not what you have expected.  Output will contain all mentioned attributes, even those, which weren't passed into a component (they will have empty values). More than that, if you will omit "id", you will get an error like: "emtpy string is not valid id".

The reason is in the EL! Attributes used in this example are of type String, thus result of evaluation of value expression is coersed to String. Values of attributes that weren't passed in are evaluated to null. EL returns "" while coersing null to String. The interesting thing is that, if EL were not changing null then those omitted attributes would not appear in the output.

The second attept would probably be:

<h:selectBooleanCheckbox value="#{value}">
  <c:if test="#{!empty id}">
    <f:attribute name="id" value="#{id}"/>
  </c:if>
  <c:if test="#{!empty onclick}">
    <f:attribute name="onclick" value="#{onclick}"/>
  </c:if>
  <c:if test="#{!empty onchange}">
    <f:attribute name="onchange" value="#{onchange}"/>
  </c:if>
  <c:if test="#{!empty class}">
    <f:attribute name="class" value="#{class}"/>
  </c:if>
  <c:if test="#{!empty style}">
    <f:attribute name="style" value="#{style}"/>
  </c:if>
</h:selectBooleanCheckbox>

Be sure, this won't work either (it may work but not as you would expect). Instruction c:if is evaluated on the stage of the building of a component tree, and not on the rendering stage.

To workaround the problem you should prevent null to "" conversion in the EL. That's, in fact, rather trivial to achieve: value expression should evaluate to an object different from String, whose toString() method returns a required value.

The final component may look like this:

<h:selectBooleanCheckbox
  id="#{ex:object(id)}"
  value="#{value}"
  style="#{ex:object(style)}"
  class="#{ex:object(class)}"
  onchange="#{ex:object(onchange)}"
  onclick="#{ex:object(onclick)}"/>

where ex:object() is a function defined like this:

public static Object object(final Object value)
{
  return new Object()
  {
    public String toString()
    {
      return value == null ? null : value.toString();
    }
  }
}

A bit later: not everything works as we expected. Such approach doesn't work with the validator attribute, whereas it works with converter attribute. The difference between them is that the first attribute should be MethodExpression value, when the second one is ValueExpression value. Again, we suffer from ugly JSF implementation of UOutput component.

Wednesday, 07 October 2009 09:16:10 UTC  #    Comments [0] -
JSF and Facelets | Tips and tricks
# Tuesday, 22 September 2009

Suppose you have a library, which is out in the production and is used by many clients. At the same time the library evolves: API is extended, bugs are being fixed, code becomes faster and cleaner, bla bla bla...

At some point you're fixing some important bug that's been hiding for a long time in the bowels of your library. You're happy that you've spotted it before clients got into troubles. You're notifying all the clients that there is an important fix, and that they need to update the library.

What do you think you hear in return?

Well, we're not perfect, there are bugs in our software. We and our clients realize this. Nothing will eliminate bugs to creep into a code from time to time.

That's a train of thought of a particular client:

We agree that there is a bug and that it has to be fixed. We, however, want to touch the library in a minimal way, as who knows what other new bugs had they introduced, so let's ask them to fix this particular bug in our version of the library.

That's fair from the client's perspective. They don't want better code, they just want that particular bug fixed!

For us, however, this means branching some old version of the library, fixing bug and supporting this branch for the particular client. It's fair to expect similar position from each client, thus should we create and support library branches per client, and branch a main branch for a new client only?

For us (Arthur and Vladimir) it looks as enormous waste of resources. We (our company) should either hire more and more scaled people or experience gradual slowdown of support and development.

Our answer could be obvious if not position of top managers who value client relations so much that they easily promise whatever client wishes. No arguments that latest version is better tested, more conforming to specifications, more reliable, faster and so on are accepted. The main argument against our position is that the client's applications run in the production, and no new potential bugs are acceptable.

Here is our dilemma: we neither can convince the client (more precisely our managers) that we're right, nor are convinced with their arguments...

Tuesday, 22 September 2009 08:16:11 UTC  #    Comments [3] -
Thinking aloud
# Wednesday, 09 September 2009

Recently we have seen a blog entry: "JSF: IDs and clientIds in Facelets", which provided wrong implementation of the feature.

I'm not sure how useful it is, but here is our approach to the same problem.

In the core is ScopeComponent. Example uses a couple of utility functions defined in Functions. Example itself is found at window.xhtml:

<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:ui="http://java.sun.com/jsf/facelets"
  xmlns:c="http://java.sun.com/jstl/core"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:f="http://java.sun.com/jsf/core"
  xmlns:fn="http://java.sun.com/jsp/jstl/functions"
  xmlns:ex="http://www.nesterovsky-bros.com/jsf">
  <body>
    <h:form>
      <ui:repeat value="#{ex:sequence(5)}">
        <f:subview id="scope" binding="#{ex:scope().value}">
          #{scope.id}, #{scope.clientId}
        </f:subview>
        <f:subview id="script" uniqueId="my-script"
          binding="#{ex:scope().value}" myValue="#{2 + 2}">
          , #{script.id}, #{script.clientId},
          #{script.bindings.myValue.expressionString},
          #{ex:value(script.bindings.myValue)},
          #{script.attributes.myValue}
        </f:subview>
        <br/>
      </ui:repeat>
    </h:form>
  </body>
</html>

Update: ex:scope() is made to return a simple bean with property "value".

Another useful example:

<f:subview id="group" binding="#{ex:scope().value}">
<h:inputText id="input" value="#{bean.property}"/>
<script type="text/javascript">
var element = document.getElementById('#{group.clientId}:input');
</script>
</f:subview>

Wednesday, 09 September 2009 11:39:14 UTC  #    Comments [1] -
JSF and Facelets | Tips and tricks

In the section about AJAX, JSF 2.0 spec (final draft) talks about partial requests...

This sounds rather strange. My perception was that the AJAX is about partial responses. What a sense to send partial requests? Requests are comparatively small anyway! Besides, a partial request may complicate restoring component tree on the server and made things fragile, but this largely depends on what they mean with these words.

Wednesday, 09 September 2009 05:54:38 UTC  #    Comments [0] -
JSF and Facelets | Tips and tricks
# Saturday, 29 August 2009

Recently we were disputing (Arthur vs Vladimir) about the benefits of ValueExpression references in JSF/Facelets.

Such dispute in itself presents rather funny picture when you're defending one position and after a while you're taking opposite point and starting to maintain it. But let's go to the problem.

JSF/Facelets uses Unified Expression Language for the data binding, e.g.:

<h:inputText id="name" value="#{customer.name}" />

or

<h:selectBooleanCheckbox id="selected" value="#{customer.selected}" />

In these cases value from input and check boxes are mapped to a properties name, and selected of a bean named customer. Everything is fine except of a case when selected is not of boolean type (e.g. int). In this case you will have a hard time thinking on how to adapt bean property to the jsf component. Basically, you have to provide a bean adapter, or change type of property. Later is unfeasible in our case, thus we're choosing bean adapter. More than that we have to create a generic solution for int to boolean property type adapter. With this target in mind we may create a function receiving bean and a property name and returning other bean with a single propery of boolean type:

<h:selectBooleanCheckbox id="selected"
  value="#{ex:toBoolean(customer, 'selected').value}" />

But thinking further the question appears: whether we can pass ValueExpression by reference into a bean adapter function, and have something like this:

<h:selectBooleanCheckbox id="selected"
  value="#{ex:toBoolean(byref customer.selected).value}" />

It turns out that it's possible to do this kind of thing. Unfortunately it requires custom facelets tag, like this:

<ex:ref var="selected" value="#{customer.selected}"/>

<h:selectBooleanCheckbox id="selected"
  value="#{ex:toBoolean(selected).value}" />

Implementation of such a tag is really primitive (in fact it mimics c:set tag handler except one line), but still it's an extension on the level we don't happy to introduce.

This way we were going circles considering pros and cons, regretting that el references ain't native in jsf/facelets and weren't able to classify whether our solution is a hack or a neat extension...

P.S. We know that JSF 2.0 provides solution for h:selectBooleanCheckbox but still there are cases when similar technique is required even there.

Saturday, 29 August 2009 13:11:26 UTC  #    Comments [0] -
JSF and Facelets | Tips and tricks
# Friday, 21 August 2009

We always tacitly assumed that protected modifier in java permits member access from a class the member belongs to, or from an instance of class's descendant. Very like the C++ defines it, in fact.

In other words no external client of an instance can directly access a protected member of that instance or class the instance belongs to.

It would be very interesting to know how many people live with such a naivete, really!

Well, that's what java states:

The protected modifier specifies that the member can only be accessed within its own package (as with package-private) and, in addition, by a subclass of its class in another package.

If one'll  think, just a little, she'll see that this gorgeous definition is so different from C++'s and so meaningless that they would better dropped this modifier altogether.

The hole is so huge that I can easily build an example showing how to modify protected member of some other class in a perfectly valid way. Consider:

MyClass.java

package com.mypackage;

import javax.faces.component.Hack;
import javax.faces.component.UIComponentBase;

import javax.faces.event.FacesListener;

public class MyClass
{
   public void addFacesListener(
     UIComponentBase component,
     FacesListener listener)
   {
     Hack.addFacesListener(component, listener);
   }

   ...
}

Hack.java

package javax.faces.component;

import javax.faces.event.FacesListener;

public class Hack
{
   public static void addFacesListener(
     UIComponentBase component,
     FacesListener listener)
   {
     component.addFacesListener(listener);
   }
}

An example is about to how one adds custom listener to an arbitrary jsf component. Notice that this is not assumed  by design, as a method addFacesListener() is protected. But see how easy one can hack this dummy "protected" notion.

Update: for a proper implementation of protected please read Manifest file, a part about package sealing.

Friday, 21 August 2009 12:25:59 UTC  #    Comments [0] -
JSF and Facelets | Tips and tricks
# Thursday, 20 August 2009

Just in case, if you don't know what JSON stands for - it's JavaScript Object Notation.

You may find a plenty of JSON implementations in java, so we shall add one more idea. Briefly, it's about to plug it into xml serialization infrastructure JAXB. Taking into account that JAXB now is an integral part of java platform itself, benefits are that you can transparently use the same beans for xml and JSON serialization.

What you need to do is only to provide JSON reader and writer under the hood of XMLStreamReader and XMLStreamWriter interfaces.

In spare time we shall implement this idea.

Thursday, 20 August 2009 06:28:37 UTC  #    Comments [0] -
Tips and tricks
# Wednesday, 19 August 2009

If you by chance see lines like the following in your code:

private transient final Type field;

then know, you're in the trouble!

The reason is simple, really (provided you're sane and don't put field modifiers without reason). transient assumes that your class is serializable, and you have a particular field that you don't want to serialize. final states that the field is initialized in the constructor, and does not change the value for the rest life cycle.

This way if you will serialize an instance of class with such a field, and then deserialize it back, you will have the field initialized with null, and no way to have another value there.

P.S. That's what we have found in our code recently:

private transient final Lock sync = new ReentrantLock();

Wednesday, 19 August 2009 04:44:42 UTC  #    Comments [0] -
Tips and tricks
# Monday, 10 August 2009

Well, we ain't a top news trackers, so only today have found that Micro Focus has acquired Borland.

Once, we were a great supporters of their C++ and Pascal software, but then something has changed. Was it an inspiration that had left them or something else?

Anyhow, their products will live for a long time, but that's a very different kind of life, similar to a lot of COBOL.

Monday, 10 August 2009 04:25:15 UTC  #    Comments [0] -

Archive
<2009 December>
SunMonTueWedThuFriSat
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789
Statistics
Total Posts: 387
This Year: 3
This Month: 0
This Week: 0
Comments: 2176
Locations of visitors to this page
Disclaimer
The opinions expressed herein are our own personal opinions and do not represent our employer's view in anyway.

© 2024, Nesterovsky bros
All Content © 2024, Nesterovsky bros
DasBlog theme 'Business' created by Christoph De Baene (delarou)