2009/04/18

RichFaces and Background Gradient

I do not know whose idea it was. Maybe it is there just to demonstrate some advanced RichFaces' abilities but I (in all the humbleness) hate it. I am talking about the background gradient which is by default present at table headers and toolbars. The background is a dynamically generated image and its presence in a web page is caused by XML snippets like the following one (part of richfaces-ui.jar:/org/richfaces/skin.xcss).

<u:style name="background-image">
  <f:resource xmlns:f="http:/jsf.exadel.com/template" f:key="org.richfaces.renderkit.html.GradientA"/>
</u:style>

A friend of mine would call such a beatiful thing a funfair or a fly-by. Apart from the hardcoded gradient background I miss only one thing in RichFaces.

A scrolling text that blinks in Firefox and Opera.

It took me couple of hours to get over the problem, yet I'm not satisfied with either solution I found.

Solution no. 1: Override the default behavior

Your CSS style can be loaded later and override the background you are not satisfied with. This is even "oficially" recommended. The linked page speaks about rich:dataTable so I am adding my part for rich:Toolbar.

.rich-toolbar, .rich-toolbar-item {
    background-image:none;
    background-color:transparent;
}     

You can of course set more convenient background color. The big issue here is that you still have the gradient style configured and loaded by your browser, and the background image generated at the server.

Solution no. 2: Update richfaces-ui.jar

You can grep through all .xcss files inside richfaces-ui.jar and remove the gradient from whatever place you want. You get tinier CSS and less work on the server side. But you have to repeate the procedure every time you want to upgrade RichFaces version. And you also must be careful about your richfaces-ui-without-gradient.jar.

I like neither of the solutions. For my project I went with no. 1 and I hope that there will be a new gradient style to configure in my skin.properties: gradientStyle=NONE.

2009/04/09

TestNG and Group Filters

Recently I solved an interesting problem with test groups in TestNG. To describe the problem, let me describe a sample test class with three methods, which are included into two groups.

public class SampleTest {
  @Test(groups = { "groupA" })
  public void testMethod1() {
    System.out.println("1 in A");
  }

  @Test(groups = { "groupA", "groupB" })
  public void testMethod2() {
    System.out.println("2 in A, B");
  }

  @Test(groups = { "groupB" })
  public void testMethod3() {
    System.out.println("3 in B");
  }
}

Usually, TestNG is called using an Ant task like the following one.

<testng excludedGroups="..." groups="..." ... />

What methods can be executed with various groups and excludedGroups setting presents this table:

MethodsgroupsexcludedGroups
1groupAgroupB
1, 2groupA--
2, 3groupB--
3groupBgroupA
1, 2, 3----

This is pretty logical. But wait, there is a combination missing from that table. What about just the method 2, which is in groupA and groupB? To be honest, I did not find an easy way to achieve this. But there is a workaround. First, you must use an external configuration file for TestNG.

<testng classpathref="...">
  <xmlfileset dir="." includes="testng.xml"/>
</testng>

In this file, you can use Beanshell to enable/disable individual methods.

<suite name="TestSuite">
  <test name="SampleTest">
    <method-selectors>
      <method-selector>
        <script language="beanshell"><![CDATA[
          groups.containsKey("groupA") && groups.containsKey("groupB")
        ]]></script>
      </method-selector>
    </method-selectors>
    <classes>
      <class name="com.blogspot.qecafe.tests.SampleTest" />
    </classes>
  </test>
</suite>

The magic line in Beanshell will cause only methods in both groups to be executed.

There is yet another item missing - 1, 3 combination. You can run it in a similar way just like 2.

2009/04/07

Temptations of Software Engineers

Have you ever been tempted to use a technology just because of the technology itself? Was the technology such a fancy thing that you could not resist? Please do not do that! A result of your work would be barely usable in the real life. Do you know the superior Swiss knife with all the stuff inside? I am in doubt you could ever carve a little wooden ship for your son with it.
Let me tell you a true story of a software engineer and an application he developed.

Once upon a time, there was a guy who decided to learn Java and all its bright features, which brought the light on every programmer's possible problem. He chose a set of features that were most interesting to him including serialization, and multi threading. To be not all alone and to verify his code, he decided to take a community as a hostage. Let's inspect a couple of his mistakes.

First, serialization is good for remote method invocation, for sending objects over network, and even for storing small project configurations into a file. It should not be used as a primary data storage, since there are relational databases for such a purpose. If you wanted to be thread safe in a serialize-everything environment, you must keep all the objects in the memory and (de)serialize them only on an application start/shutdown. It is slow, complicated and inefficient way.

Second, multi threading is a powerful thing but it is like the fire - it can be very dangerous. Threads are not independent processes. You should be careful about them, especially if they are running third party code. Apart of that issue, the biggest problem was that Thread.stop() does not stop a waiting thread on all JVM implementations. It is not good idea to stick to an implementation detail. Later, Thread's methods stop(), suspend(), and resume() have become deprecated because it showed up that they are unsafe.

I could have continue here with similar cases but that should be enough to show what I meant by temptations. If the project were now buried deep in the binary scarp, everything was fine. Unfortunately, the community around it become large and the project is massively used nowadays. And the users must fight with those design issues hidden deep inside of it.

2009/04/01

Guts of Programming Languages

What makes it difficult to master a new programming language when you already know one or two? Is it a fancy syntax? Is it an API? I do not think so.

A syntactic sugar is not the real matter of the programming art. It should be only a hammer for your nails. Usually, a new syntax is not so much different. I mean how often do you meet a brand new paradigm? There is imperative, functional, logic and whatever programming, but you have probably chosen your way already.

Modern IDEs can help you with the API of the new language. Again, API should not be an obstacle. But there is still a thing that you must be aware of...

I do not know of any real programming language that isolates a programmer from its inside behavior (by a real programming language I mean a language that is commonly used for developing long running applications). You always need to be aware of a memory model, of a garbage collection mechanism, of a just in time compilation, of a target system architecture, of registers size, of a class inner representation, of a variable size in bytes...

There are too many "of". I wonder when there is a language that allows developers to concentrate completely on the main problem. A friend of mine suggested that PHP is such a language but I do not agree with that. It is a language which leaves a field of corpses behind itself and must finish processing sooner than anybody reveals this fact.

I have a favorite programming language, which isolates me at most. It is in the functional languages family, and it is called Haskell. You can even write a GUI application in Haskell, but an application server would be a death match.

So good luck in those hard times and do your best for you not to forget any single language implementation detail...

. .