Tuesday, January 26, 2010

Simple Calculator Using Swing Part II

I talked about some GUI components that you can use in my previous post. In this post, I will explain to you how to use those GUI components.

Buttons and Text Fields are useless unless they do something, right? Some actions are triggered if you click a button. So far what we have is just display. You can run the code and will see that nothing happens when you click a button. So, now, I am going to implement an action method. Here's the code snippet : (You can click on the code to see it bigger)

You just call addActionListner() of JButton. addActionListner() take an ActionListener object. As you see it, we're passing our class SimpleCalculator to addActionListener(). ActionListener is an abstract class that has the method actionPerformed(). An abstract class has methods that haven't been implemented. So, whatever class that uses abstract class have to implement those methods in the abstract class. In ActionListener abstract class, there's an actionPerformed method. So we're going to write the code for actionPerformed method in our class. Also, you need to make sure that you declare :

public class Calculator implements ActionListener

and here's our actionPerformed() method.


The logic here is simple. Now, when you click the number buttons, you should be able to those in the text field.

Saturday, January 23, 2010

Simple Calculator using Java Swing Part 1

I wrote about Java Swing and its components in my previous post. Now, it's time to move on to the next steps which is learning how to make use of those components and create an application. Of 'course, I didn't talk about all the components that come in the package. But we will encounter some new ones in a few. I personally think that you learn the most when you have a concrete example or project that is useful and applicable to the real world. Therefore, I decided to write a program called A Simple Calculator. This will be a long post. So, I'll try my best to highlight the most important notes. I also want to extend this project to a few posts. So, in this post, I'll talk about the layout of a swing application. The following is a screen shot of my simple calculator.


It's a simple calculator : it has a couple of JButtons and one JTextField. (You can use JLabel in the place of JTextField). What is not obvious here is that I used GridLayout and BorderLayout for the layout of the buttons.

By default, JPanel comes with a FlowLayout(It will be discussed in later posts). You can change default layout of a JPanel when you create a new JPanel by specifying in the constructors or you can explicitly call setLayout() method of JPanel. For this program, I used a mixture of BorderLayout and GridLayout. I used two GridLayouts because I wanted all numbers on the left side and all the signs on the right side.



So, we have the mainPanel which is holding all the different panels with different layouts. The mainPanel's layout is BorderLayout as I want to put the text field and the buttons on top of each other. And there's another buttonsPanel which holds two smaller panels : numbersPanel & signsPanel. The reason is that that two different button panels are different in terms of number and arrangement. buttonsPanel has also a BorderLayout because BorderLayout allows the two panels to be placed on left and right sides. And each smaller button panel has GridLayout which is self-explanatory.

You need to add the following 3 lines of code in the end to put everything on the panel.

buttonsPanel.add(numberPanel, BorderLayout.WEST);
buttonsPanel.add(signsPanel, BorderLayout.EAST);

mainPanel.add(buttonsPanel, BorderLayout.CENTER);

You will see that I created JButton and add an actionListener to it. I'll talk about it in my next post.

Monday, January 11, 2010

Hibernate : Deleted Entity Passed to Persist

I use Hibernate and Seam in my project. In using advanced technologies which were not taught in the classrooms, I had to learn about Hibernate mappings, Seam POJOs, EJBs and Java Persistance through books, Googles and other forums. Often, we ran into problems that we didn't know how to solve. Times like that we turned to Internet to find solutions. I ran into a problem last week that I was so dreaded of a few months ago. We thought we fixed the problem but apparently it came back and haunted us. Somehow, I googled for a solution and someone posted an idea on a blog that helped me solve my problem. So, I'm writing this post sharing what I learned and hoping that some one will actually find my post helpful.

This error that I was dreaded of was "Deleted Entity Passed to Persist" error. This is not the type or name of the error. It is what Java revealed in the logs and it can't proceed because of the "Deleted Entity Passed to Persist". In the past, we noticed that it happened when we tried to remove an entity from database by using entityManager.remove(entityname). For those of you who have worked with EJB will know what entityManager is. Basically it's trying to delete a row of data from database and it's doing so by calling an API.

Let's say I have an entity called Person and a second entity called Credit Card. A person can have one or more credit cards. So, we created a one-to-many relationship between Person and Credit Card. Person has become a table in the database and Credit Card has become another table in the database. Credit Card table has a foreign key column called Person_Id which stores the Id of the person from Person table. We created two way relationship.

class Person{
@OneToMany
private List creditCards = new ArrayList();

//getter & setters etc.

}

class CreditCard{
@ManyToOne
private Person person;
}

We put one relationship in Person entity and another relationship in CreditCard entity. (Note: the above code is NOT complete, you will need to ask other annotations for it to work properly). By doing so, you will see two way relationship, i.e, if you look from Person entity, you will see it's connected to Credit Card entity and if you look from CreditCard entity, you will see it's connected to Person entity. Now if you want to delete a credit card record from the Credit Card table, you need to first take out the relationships between the Person and that Credit Card.

We used to set the Person Id to 'null' and then call the remove() method from the EntityManager. But doing so gives the above error.

I finally found out the solution that nullifying a column doesn't take out the relationship in this matter. Since this is two way relationship, we need to take out that credit card from the arrayList in the Person table. So instead of doing entityManager.remove(creditCard), we have to do this :

person.getCreditCards().remove(c); // c is a credit card
entityManger.remove(c);

This is also a proper way of removing entities. You should get no "deleted entity passed to persist" error by adding an additional line of code.

Friday, January 8, 2010

Reality Vs. Customer Satisfaction

In enterprise IT world, there's always a debate between what's the right way to do things and what the clients want. What might please our clients might not always be the best solution. As I've been wadding towards my third year milestone of job experience, I've encountered so many situations where what our clients specified a requirement, we implemented it and later on they wanted to change it again. I used to think that as a service provider, I should always provide customers what they want. But sometimes, a firm objection (as long as you have a solid reason) is needed to avoid regular updating and changing of the code.

I'm writing this post in relating to an event that happened a few days ago, which is related to what I was talking above. In my project, we need to capture our client's information such as name, dob and etc. We also need to capture the marital status of each of our client. The old implementation was such that any clients under 16 will not be asked of their marital status. This specification has been requested by our analyst who left. For me, I don't think 16 is not a realist number for this situation. There're a couple instances where 14, 15 years old can be a parent. But he was the analyst and I thought he would have known better.

Now after one year since when the system has gone live, they started complaining about the age restraint. They started questioning why we chose 16 to be the limit. Honestly, I had no idea. So, after a few brainstorming, 13 was chosen to be the decision point. And we told our client that this will be the final decision and no further changes should be made about it. For me, I really didn't think 13 was the right solution. There is always something else.

So guess what? The other day they found out there's a 12 year old parent. It's a sick world. But it's the reality. My coworker did some search on Google about the youngest parent in history and 5 was the youngest one. (If you want detailed information , you can view here. ) Now the question is do we put 5 as the decision point instead of 13. Or do we take out the age restraint at all? Anyone under 5 could never be a parent. But you will never know in this bizarre and strange world. When it came down to user satisfaction, how far can we go?

Wednesday, January 6, 2010

JFrame



The last post was creating a very simple hello world swing application using JFrame, JPanel and JLabel. In this post, I would like to post a bit more about JFrame.

JFrame is one of the three top-level container classes that come with Swing. The rule of thumb is that each Swing application has AT LEAST ONE top-level container. The above figure is a JFrame and in this application, we have one top level container, which is a JFrame. In our JFrame, we have a menu bar(y'all know what a menu bar is) and a content pane(the yellow background). In a containment hierarchy, this is what the above figure looks like
JFrame
|
------- Content Pane
|
------- Menu Bar

Content pane can be customized and new components can be added to our original Swing application. In my previous example, I added a label to the content pane. We can call content pane directly from JFrame by the method frame.getContentPane(). But we used a slightly different approach last time. We created a JPanel component and then added it to JFrame. In my last post, I explained that content pane existed inside JPanel. It was my mistake to misuse the word since I'm using contentpane as a variable name.

What I really meant was that I was trying to create a customized content pane. when we call frame.getContentPane(), we actually get a container object, not a JComponent object. ( I will talk more about JComponent in my next post). Since I wanted to make use of JComponent features, I needed to either type cast or create my own content pane. In this case, I created a JPanel and added to JFrame, making my contentPane JPanel a content pane.

As I mentioned above, JFrame is one of the top-level containers. In Swing, there are two other top-level containters : JDialog & JApplet. Each standalone Swing application has JFrame as root container and each applet application has JApplet has root container. If we have an application that has a dialogue box, then there will be two top-level containers in this case, which are JFrame & JDialog.