Monday, November 29, 2010

c++ is the future? the present?

I was away for a long time, not because I don't have anything to say, just because I was working on my own product, I created d-jon (check it out in http://d-jon.com).

But why am I telling you this? because I want to discuss what is the best language for multi-platform desktop applications.

I've been working in c++ for the last few months, and I'm in love with that language, but... as most of the love experiences it started with hate... sometime ago I'd to work in c because most of our Universities had it as the main language and you should do all the homeworks on it... as usual you felt on some typical mistakes like memory leaks, unwanted behaviours, etc. But lately I started to wonder how difficult is to create applications for desktop in java... (hey... wait, don't kick your reading, let me explain why), I'm one of the java swing lovers, I think it's a great part of java and it has a very good architecture, it's flexible and etc.

But one of the problem of java desktop applications it's the java itself, imagine the following scenario. You created a desktop application and you want to distribute it, you're going to face one problem... you can redistribute the jre with your application or you could let the user use their current version (if they've any) or download the lastest jre version available on internet. Both scenarios have their own challenges, like: where am I going to put the java in order to avoid the JAVA_HOME and/or CLASSPATH environment settings problem?, what if they already have another java version required by some other applications? I know, you can install as much as java versions as you need, but that's true if you know what you're doing and face the settings in a batch file... not if you want to put your software and get 100 downloads every day and expect that each user has this knowledge. Other problems that comes to my mind, is how are you going to handle some native tasks relying on the operating system? let's use d-jon as an example of this, if I need to get the "idle time" you cannot install a hook or something using java... maybe you will jump and say: "hey!!! you can use the native calls to create this" that's true... but you'll need to create all the stuff that comes to this approach, it's not easy after all, and what if you are creating an application that will be deployed in several platforms? like linux, windows and mac? each platform has its unique APIs to do the same thing, in C you could use conditional compilation and create a different executable for each platform and that's it, if you address this in your architecture you will be able to do what ever you want. Other issues that comes to my mind, now that I wrote apple, is how to you create a native look and feel in java? it's not possible, you could use look'd feel and put your buttons with the same look as mac... but you will not be able to put the menu in the mac's main menu, like the native applications does. And what about system tray icon? I know that java implemented that in java 6... but mac does not have java 6, their last version is 5.

Last, but not least, what about the swing performance? d-jon should be deployed in new computers as well as old pcs, and I need to address a very big gantt diagrams, swing is not really that good.

My conclusion is... if you want to do a good shopping cart web application use java... it's the killer, if you want to use an application that will be on internet, and you don't have the money or infrastructure to create your own public server, use PHP and if you want to create a very good desktop application that will be portable across all kind of OS and architectures use C++ with Qt, GTK or any other multi-platform framework, my advice... use the right tool for the right job.

Wednesday, October 14, 2009

Dynamic Navigation in JSF

The last two post was about the use of dynamic JSF components and properties, but the other problem I faced is referred with the dynamic navigation,

"How can I extend or write a more dynamic navigation in JSF? for example to create dynamic parameters or calls to a non jsf pages with GET parameters?"

Ok, here's how I solved this. In the method of the backing bean that will be called when I the button is pressed I added this code:


FacesContext currentInstance = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse) currentInstance.getExternalContext().getResponse();
HttpServletRequest request = (HttpServletRequest) currentInstance.getExternalContext().getRequest();
String url = request.getContextPath();
if (a == 1) {
url += "testpage.jsp?arg1=1&arg2=2";
} else {
url += "testpage2.jsp?arg1=1&arg2=3";
}
response.sendRedirect(url);
currentInstance.responseComplete();


As you can see here the solution it's very simple and works very well.

Tuesday, October 13, 2009

How Can I bind the jsf properties dynamically?

In my previous post I explained how you would be able to create the controls dynamically, now it's time to bring this baby alive!

First, let me explain how you would create Value Expressions (that will be used by faces to get the values) and bind them to your recently created HtmlInputText,


FacesContext facesInstance = FacesContext.getCurrentInstance();
Application application = facesInstance.getApplication();
ExpressionFactory expressionFactory = application.getExpressionFactory();

String expression = "#{myMode.myProperty}";
ValueExpression valExpression = expressionFactory.createValueExpression(facesInstance.getELContext(), expression, String.class);

HtmlInputText text = new HtmlInputText();
input.setValueExpression("value", valExpression);


Easy, isn't it? the first 3 lines will get the context required to create the ValueExpression, the line "String expression = ..." just creates the string expression, the one that you usually put in the value of the h:inputText in your jsf page. The next two lines create the expression and assign it to the "value" property of the html input text. You could use this in the required or rendered fields (any property that you could use as EL in your page).

This solution works well if you have your properties hardcoded in your bean, but how will this work with a really dynamic solution? (if you already know them, why will you need to create all the dynamic controls in the first place?)

Ok, here the Expression Language will do the trick, the Expression Language allow you to put Maps as properties in your code, so you could create your own Map to your dynamic properties and that's it! here's a sample of the Map (I will not put all the methods you should figure out how to solve the others, but it's very simple)


public class MyPropertyMap implements java.util.Map {
private java.util.HashMap internalMap;
public EntityMap() {
internalMap = new java.util.Map();
internalMap.put("PropertyA", 1);
internalMap.put("PropertyB", "A text property");
internalMap.put("PropertyC", True);
}

public Object get(Object key) {
return internalMap.get(key);
}

public void put(Object key, Object value) {
internalMap.put(key, value);
}

... (all the other methods required by the Map interface)
}

public MyModel {
private MyPropertyMap map = new MyPropertyMap();

public Object getMyPropertyMap() {
return map;
}

public void setMyPropertyMap(MyPropertyMap map) {
this.map = map;
}
}


finally your dynamic control creation should look like this:


FacesContext facesInstance = FacesContext.getCurrentInstance();
Application application = facesInstance.getApplication();
ExpressionFactory expressionFactory = application.getExpressionFactory();

String expression = "#{myMode.myPropertyMap['PropertyA']}";
ValueExpression valExpression = expressionFactory.createValueExpression(facesInstance.getELContext(), expression, Integer.class);

HtmlInputText text = new HtmlInputText();
input.setValueExpression("value", valExpression);
myPanel.getChildren().add(input);

String expression2 = "#{myMode.myPropertyMap['PropertyB']}";
ValueExpression valExpression2 = expressionFactory.createValueExpression(facesInstance.getELContext(), expression2, String.class);

HtmlInputText text2 = new HtmlInputText();
input2.setValueExpression("value", valExpression2);
myPanel.getChildren().add(input2);

String expression3 = "#{myMode.myPropertyMap['PropertyC']}";
ValueExpression valExpression3 = expressionFactory.createValueExpression(facesInstance.getELContext(), expression3, Boolean.class);

HtmlSelectBooleanCheckbox chk = new HtmlSelectBooleanCheckbox();
chk.setValueExpression("value", valExpression3);
myPanel.getChildren().add(chk);


and that's it... you have a full Dynamic page! (I hope you noticed how the 3rd parameter of the createValueExpression changed for each control, Integer, String and Boolean).

Ok, with this you will have a full dynamic solution, the next part will show you how you could create dynamic navigation using dynamic parameters.

Dynamic JSF

Recently I came across with a "problem", how can I create some JSF pages more dynamic than usual?, for example adding new controls on the fly using metadata from somewhere else. I decided to write this article because it's a little hard to find information about this subject, and when you find it you could not spot all the solution and all the problems that will face in the real life :D.

This is not a solution I invented and I can barely remember all the links I read in order to understand the whole picture, later I will try to look at my browser history in order to compile them and give the credit they deserved.

Ok, here is the description of the problem I want to solve:

How can I create dynamic controls for a page that needs to be solved on runtime? the application I'm working on is a BPM engine (BizAgi) that constructs its pages based on metadata information stored in a DB, so it's not possible to write the controls from the beginning.

The solution is fairly simple and has 3 parts:

1. Dynamic creation of the controls
2. Dynamic mapping of the properties
3. Dynamic redirection to a JSP using parameters.

Dynamic control creation

This is the easy part and there's a lot of documentation in internet about this subject, and the steps are easy:

1. Create a Panel in your JSF page
2. Bind the panel to a property in your backing bean
3. Add the controls in your backing bean

so, here's how it's done:

create a bean class (model class) with a property of type javax.faces.component.UIPanel like this:


public class MyModel {
private javax.faces.component.UIPanel myPanel;

public javax.faces.component.UIPanel getMyPanel() {
return myPanel;
}

public void setMyPanel(javax.faces.component.UIPanel myPanel) {
this.myPanel = myPanel;
}
}


Next just bind it in your jsf page like this:


<f:view>
<h:panelGrid binding="#{myModel.myPanel}" />
</f:view>


we're close to finish, the next step is where the fun begins, just add the code to create dynamically the controls, like this:



public void setMyPanel(javax.faces.component.UIPanel myPanel) {
this.myPanel = myPanel;
if (myPanel.getChildCount() <= 1) {
HtmlInputText input = new HtmlInputText();
input.setValue("my dynamic text");
myPanel.getChildren().add(input);
}
}


At this point, I'm sure you noticed the "getChildCount() <= 1"... why is that? just because everytime the postback is called the faces framework will set the panel with the last controls added to it, if you don't control that you will get a panel with multiple text everytime you hit the "save" button. I know, you can do this in several ways, but this is an example!

Ok, this is the point where all the "blog" gurus stop and you get yourself in the middle of nowhere!, you must ask questions like... how will I bind that to dynamic properties instead of static texts? or, how would I manage the state... etc.

Because the blog is getting longer than I thought I will split this in some parts...

How can I bind the jsf properties dynamically?
How can I send dynamic parameters to other JSPs? or JSFs?

As usual please forgive my pour english, I'm hoping to improve it with every post xD

Friday, September 5, 2008

Websphere Application Server Community Edition (WAS CE) Clustering using WADI

by Rockfield.

Working on the latest version of BizAgi, we were looking for an app server that supported JDK 1.6, EJB 3.0 and, of course, clustering. One of our targets was WAS CE, and as the WAS CE Cluster through WADI is explained at the IBM website, you might think it's easy to build. However, as long as you start following the instructions you'll soon realize it's not as simple, clear and quick as shown in there. So this will be a "for dummies" walkthrough for most people who are not expert enough to overcome the possible problems that might occur when building the cluster.


Previous considerations
  • For this specific example WAS CE 2.1 was previously installed on 2 machines called server1 and server2. No special configuration was used, just the plain default installation.

  • Default ports are used, and they are the same for both machines.

  • In order to check the cluster behavior, a load balancing HTTP server is necessary. A plain Apache HTTP Server installation and configuration is provided at the end of this tutorial.

  • <WASCE_HOME> is the WAS CE installation directory.

WAS CE cluster configuration

NOTE: These steps must be executed on both servers!
  • Go to the file <WASCE_HOME>/var/config/config-substitutions.properties and assign a name to each node of the cluster replacing the value of the clusterNodeName property (by default this property's value is "NODE"). For this example we used "node1" on server1 and "node2" on server2.
    clusterNodeName=node1
  • On the same config-substitutions.properties file go to the RemoteDeployHostname property and replace the default value "localhost" with the actual server name or IP address.
    RemoteDeployHostname=server1
  • Go to the <WASCE_HOME>/var/config/config.xml file (NOTE: Make sure the server is NOT RUNNING while editing the config.xml, because when stopped all changes made while running will get lost) and look for the following tags in order to switch the load property to "true" if it does exist and is set to "false":
    <module name="org.apache.geronimo.configs/tomcat6-clustering-wadi/2.1.1/car" load="true"/>
    <module name="org.apache.geronimo.configs/wadi-clustering/2.1.1/car" load="true">
    <module name="org.apache.geronimo.configs/farming/2.1.1/car" load="true">
    NOTE: If the value is set to "true" while not running, when the server starts up, the load property disappears. It is only shown explicitly when its value is set to "false".
  • On the same config.xml file, look for the org.apache.geronimo.configs/farming/2.1.1/car key. You must add all the cluster nodes except for the current one which is already there by default. This is how the key would look like for our server1:
    <module name="org.apache.geronimo.configs/farming/2.1.1/car">
    <gbean name="NodeInfo">
    <attribute name="name">${clusterNodeName}</attribute>
    </gbean>
    <gbean name="ClusterInfo">
    <attribute name="name">${clusterName}</attribute>
    </gbean>
    <gbean name="org.apache.geronimo.configs/farming/2.1.1/car?ServiceModule=org.apache.geronimo.configs/farming/2.1.1/car,j2eeType=NodeInfo,name=NodeInfo2" gbeanInfo="org.apache.geronimo.farm.config.BasicNodeInfo">
    <attribute name="name">node2</attribute>
    <attribute propertyEditor="org.apache.geronimo.farm.config.BasicExtendedJMXConnectorInfoEditor" name="extendedJMXConnectorInfo">
    <ns:javabean class="org.apache.geronimo.farm.config.BasicExtendedJMXConnectorInfo" xmlns="" xmlns:ns4="http://geronimo.apache.org/xml/ns/attributes-1.2" xmlns:ns="http://geronimo.apache.org/xml/ns/deployment/javabean-1.0">
    <ns:property name="username">system</ns:property>
    <ns:property name="password">manager</ns:property>
    <ns:property name="protocol">rmi</ns:property>
    <ns:property name="host">server2</ns:property>
    <ns:property name="port">1099</ns:property>
    <ns:property name="urlPath">JMXConnector</ns:property>
    <ns:property name="local">false</ns:property>
    </ns:javabean>
    </attribute>
    </gbean>
    </module>
  • NOTE: On the other hand, for our server2's configuration the <attribute name="name"> tag's value would be "node1", and the <ns:property name="host"> tag's value would be "server1".

Starting the cluster

Once the node configuration is done, start the cluster nodes as you usually would if they were stand alone. In order to verify that they are clustered, on the console screen of the first running node will appear the following notification when the second node would had started:
Dec 12, 2012 11:11:53 AM org.codehaus.wadi.tribes.WadiMemberInterceptor memberAdded
INFO: memberAdded:tcp://{-84, 16, 2, 16}:4000

Application configuration

  • Add a <distributable/> tag in your application's web.xml file.

  • Check inside your deployment plan xml file, at the war definition, and add the <dep:tomcat-clustering-wadi> tag so it would look like this:
    <dep:environment>
    <dep:moduleId>
    <dep:groupId>com.javaxcross.tests</dep:groupId>
    <dep:artifactId>WarTest-war</dep:artifactId>
    <dep:version>1.0.0.0</dep:version>
    <dep:type>war</dep:type>
    </dep:moduleId>
    </dep:environment>
    <dep:tomcat-clustering-wadi></dep:tomcat-clustering-wadi>
    where, of course, you should replace the groupId, artifactId and version tags with you own app's data.

Application Deployment

In order to deploy an application on the cluster, the web console does not have the necessary options, so you must open a command console window and execute the following instruction:

deploy.bat --user <name> --password <word> <command> --targets <target> <module> <plan>

where...

  • you'll find deploy.bat (or deploy.sh for unix like o.s.) at <WASCE_HOME>/bin/deploy.bat

  • <name> is the username and <word> is the password you use to login the web console. Default values are: system/manager.

  • <command> is the required instruction to execute, in this case could be deploy or distribute. The difference relies on deploy starting the application after the distribution, while distribute doesn't.

  • Replace <target> with the destination repository. which must be MasterConfigurationStore, because of the cluster. If you need to know the exact data you should use on the <target> tag, run GShell (<WASCE_HOME>/bin/gsh.bat), provided by WAS CE installation, and run the following command
    deploy/list-targets
    to list all the posible destination repositories. Just in case you don't find MasterConfigurationStore, execute on GShell the following command
    deploy/start org.apache.geronimo.configs/farming//car
    copy the whole MasterConfigurationStore value and add it to the command replacing the
    <target> tag, the default value is:
    org.apache.geronimo.configs/farming/2.1.1/car?ServiceModule=org.apache.geronimo.configs/farming/2.1.1/car,j2eeType=ConfigurationStore,name=MasterConfigurationStore
    The fist command used on GShell will ask for username and password, use the username/password combination you usually use for connecting through the web console.

  • <module> is the application (ear, war or jar) you want to deploy on the cluster.

  • <plan> is the xml file with the deployment plan.

Verification of the application deployment on cluster.

Once the application has been deployed, you may check if the process ended successfully verifying the following items:
  • Check the virtual repository MasterConfigurationStore for the application in the machine where the deploy command was executed on, what means, look for the application in the <WASCE_HOME>/master-repository/ directory.
  • Check the actual repository ClusterStore for the application in all of the cluster nodes including the one where the deploy command was executed on, in other words, look for the application in the <WASCE_HOME>/cluster-repository/ directory

Starting/stopping the application

Using the web console you can start the application on each node separately. But if you want to start the application on all nodes of the cluster at the same time, you must open a command console window and execute:
deploy.bat --user <name> --password <word> <command> <module>
Where...

  • you'll find deploy.bat (or deploy.sh for unix like o.s.) at <WASCE_HOME>/bin/deploy.bat

  • <name> is the username and <word> is the password you use to login the web console. Default values are: system/manager.

  • <command> is the required instruction to execute, in this case could be start or stop.

  • <module> is the name wich the application was registered with when deployed on the master repository, for instance, com.javaxcross.tests.WASCEtest/1219953325295/car

Friday, June 20, 2008

JMS Send/Response implementation

In this article I want to talk about how you will create a send/response service using JMS.

There're several reasons to turn an asynchronous thing into a synchronous process, one of them is the following problem: What if you need to call an external service and you will not know how much time that will takes, but you don't want your user seat in front of the page forever? That's one of the problems I faced up some days ago, and because of that I'm writing this.

Not all the JEE implementations provide a timeout for a method transaction, some of them does and you can put a timeout for a method in the vendor specific deployment descriptor, but it's not required by the EJB spec and, if you want a JEE compliant application, you should work with the specification. There's an annotation "@TimeOut" you could use, and it's a standard supported annotation, but this will not help you at all to solve this problem, but explaining the uses of timers is not the focus of this article (if you need clarification on this, just post a comment...)

JMS Background

The sample below uses some JMS basic concepts you need to know about, so If you surf through Internet you will find a lot of tutorials about how to write a client/server JMS stuff, and I will not copy them. In order to fully understand this article I suggest you to take a bird view of Java Sun tutorial for JEE http://java.sun.com/javaee/5/docs/tutorial/doc/.

In the "normal" samples found in Internet you will find a typical solution, a simple java client and a simple java listener, but how everything works if the sender is an EJB Session bean and the JMS receiver is a MessageListener bean?

ok, lets start with the normal sample, a client sends a message to a MessageDrivenBean and the client continues with its life.


@MessageDriven(mappedName = "jms/MyQueue", activationConfig =  {
@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")
})
public class MyMessageDrivenBeanBean implements MessageListener {

public MyMessageDrivenBeanBean() {
}

public void onMessage(Message message) {
System.out.println("Received");
}
}


Here the server just gets the message and does nothing with it. The Client code is inside a Session bean method:

@Resource(name = "jms/MyQueue")
private Queue myQueue;
@Resource(name = "jms/MyQueueFactory")
private ConnectionFactory myQueueFactory;

public void sendReceiveMessage() {
try {
Connection conn = myQueueFactory.createConnection();
Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
TextMessage textMessage = session.createTextMessage("Test");
MessageProducer producer = session.createProducer(myQueue);
producer.send(textMessage);
producer.close();
session.close();
conn.close();
} catch (JMSException ex) {
Logger.getLogger(ClientBean.class.getName()).log(Level.SEVERE, null, ex);
}
}


The client code does not have anything new; it just creates a connection, a jms session with this connection, a Text Message and sends it to the JMS pool.

What's next? We will send a callback in the client message and it'll try to listen for a response on it.

JMS Callback

        // Creates a callback queue
TemporaryQueue tempQueue = session.createTemporaryQueue();
textMessage.setJMSReplyTo(tempQueue);
producer.send(textMessage);

With this simple code we created a new Queue that will exists only for the current Connection, and will let us receive the response message, and here is the code to receive that message:

        conn.start();
MessageConsumer consumer = session.createConsumer(tempQueue);
Message response = consumer.receive(10000);
if (response != null) {
System.out.println("Response received");
} else {
System.out.println("Response not received due to timeout");
}
consumer.close();

We created a message consumer using the temporal queue and listen for a response on it for 10 seconds (10000 milliseconds), if the message response is null we will know the time out was reached.

JMS Callback sender

In the code above we created a Temporal Queue and assigned it to our message, so we will be able to get it from the server side and use it to send the response.

public void onMessage(Message message) {
try {
System.out.println("Received");

if (message.getJMSReplyTo() != null) {
Connection conn = myQueueFactory.createConnection();
Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer producer = session.createProducer(message.getJMSReplyTo());
producer.send(session.createTextMessage("Response message"));
producer.close();
session.close();
conn.close();
}
} catch (JMSException ex) {
Logger.getLogger(MyMessageDrivenBeanBean.class.getName()).log(Level.SEVERE, null, ex);
}
}

Note: the connection factory was injected using the @Resource annotation.

Ok, you will get the JMSReplyTo and you'll send a message to that queue, this destination will be the temporally queue you created in the client side.

And that's it.... but... is not!, you must take care of two things to work this out, the first and most important... if your session bean (the sender) is in a transaction the message will not be send until the end of the transaction is reached, so the consumer will wait for the 10 secs and will always write the message "Timeout....", how can we fix this? just put the annotation "@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)" in the caller method. And second... if you don't put the line "conn.start()" just before the consumer receive method call the consumer will not start listening... and you will get a "Timeout" message again. So beware of this two lines, they drove me crazy until I figured out what was going on the first time.

Full code of the application is downloadable from Full project download it's a netbeans project so you will be able to open it with that IDE, or just browse for the code in the subprojects JMSSendResponse-ejb and JMSSendResponse-war (actually it does not nothing but calling the sessionbean).

Wednesday, April 9, 2008

Is Swing slow?

The main problem with this question is the question itself, is a Windows application slow? is the minesweeper slow? are the legacy applications slow?



Everything depends on how you use it, if you have a car, lets say Ferrari, if you use it in the first gear all the time the answer will be "YES THE FERRARI IS THE SLOWEST CAR IN THE WORLD", but is it true? is the Ferrari slow? or is the driver the main problem? you would agree that the driver will have to take some lessons... ok... now let me do the question again: "Is Swing slow?" the answer: NO, Swing is as slow as the architect and developers are, if the swing applications have problems then we will not change the Framework, we need to change the Driver!



The architect and the developer must consider how the platform works under some circumstances and take care of the details, that's true even if you work on a windows application. Swing provides some advantages that you could not have in other languages, but it comes with responsibilities.



But, the theory could say something different from the experience, so lets put hands on and measure some times from the sample posted in the last article Swing Fast sample.



.NET vs Swing Time measure

I created a very simple class to measure the loading time in both applications, the following is the class I used in Java:




public class Timer {
private static long startTime;

public static void registerStartTime() {
startTime = Calendar.getInstance().getTimeInMillis();
}

public static long getElapsedTime() {
long currentTime = Calendar.getInstance().getTimeInMillis();

return currentTime - startTime;
}
}


and here's the .NET version:




public class Timer
{
private static long startTime;

public Timer()
{
}

public static void registerStartTime()
{
startTime = DateTime.Now.Ticks;
}

public static long getElapsedTime()
{
long currentTime = DateTime.Now.Ticks;
return currentTime - startTime;
}
}


ok, I put the statement Timer.registerStartTime(); in the main code just before the invocation of the screen, and the Message.show("Time: " + Timer.getElapsedTime()); just after the screen loaded. These are the results:




















Java ms..NET ms.
187156
125156
125156
125156
125156



(sorry for the extra space, I don't know why the blogger added this :s)

The average time for Java is: 137.5ms and 156ms for .NET, off course... I will not say at this moment that java is faster than .net, this is just the simplest sample, we need to do more tests and more complex scenarios. But the point is... if the starting time is pretty close, why the application will be slower in java than in .net? again, everything depends on how you use the technology.

New Scenario

Ok, what if we increase the number of components and the data on them? the new scenario has 4 new combos, each one with the letters from "a" to "z" as items, so what's now?





















Java ms..NET ms.
156156
157156
156156
156156
156156
157156


So, now the times are very close, right? ok, still too easy right?, I added a JTable in the swing application with 3 Columns and 20 Rows and the time is still the same 156ms!!!.

Conclusion

Most of the problems with the Client applications are not related with the platform or the framework, most of them are because of the abuse of the code, some developers (and also the architects) believe that the code in the client could do whatever they want and do a lot of rookie mistakes (I will talk about that in a new article). The main idea of this article is to prove you that Swing is not slower than other languages, most of the problems with the Swing applications are related with some of the following problems:

- Misunderstanding of the caching systems in the jndi lookups.
- Abuse of the workload in the Constructor of the class
- Abuse of the round trips to the server (when the screen gets the data for combos, tables, etc.)
- Coding problems because the Notepad coding technique.
- Performance problems in the JDK 1.4

and some others I will work on later, with their solutions.

We're close to the main topic of this series, how to build an enterprise applications with Swing as front-end and EJB as backend.