Sunday, December 09, 2012

Handling JSF Exceptions in CDI based applications


If jsf and cdi are used in an application, jsf lifecycle methods that aborts the jsf lifecycle must not be called in jsf phase listeners.

CDI integrated with JSF using a JSF phase listener, resources such as conversation context are reseved by CDI in beforephase method that called in restore view phase. Also CDI resources released in afterPhase method of phase listener during render response phase. When you reach to render response phase resources released unconditionally  by CDI. 
 
If we call methods such as responseComplete that aborts the calling of afterPhase methods, resources released in after phase methods is not released and CDI resource locks unreleased . You may encounter with ConversationBusyException during the next request.



Wednesday, June 15, 2011

JavaFX 2.0 Sample Application

After waiting a long time for it , finally javafx 2.0 beta was released.

I downloaded netbeans IDE 7 and Javafx FX 2.0 plugin. After playing with several javafx sample projects everthing seemed fine and I decided to develop a new application based on my sample finance project available at http://code.google.com/p/seahorse-ria-framework/downloads/list.

You can also download javafx 2.0 based sample client application from http://code.google.com/p/seahorse-ria-framework/downloads/list.

Sample javaFX client application contains a login and customer search page. For the authentication and customer search operations JEE based server side application is called from JSE based javaFX application.


I already had sample server side business project uploaded to google code, so I needed only to develop javaFX based rich client application that calls existing server based application.

Developing a sample application took several hours, most of job was coping codes from javafx samples projects into my sample project. A few thing did not  worked as I expected.(promp text ) .

Generally everthing was fine and it was very simple to develop an application with Javafx 2.0. 

Following diagram shows software architecture of sample application;








Following code segment shows login page;

 package com.seahorse.test.javafx;


import com.seahorse.bean.config.property.PropertyHelper;

import com.seahorse.bean.constant.SeaHorseConstants;

import com.seahorse.bean.container.BeanHelper;

import com.seahorse.common.util.ExceptionUtil;

import com.seahorse.support.web.SeaHorseStandaloneInitializer;

import com.seahorse.test.service.LoginService;

import javafx.application.Application;

import javafx.event.ActionEvent;

import javafx.event.EventHandler;

import javafx.geometry.Insets;

import javafx.scene.Scene;

import javafx.scene.control.*;

import javafx.scene.image.Image;

import javafx.scene.image.ImageView;

import javafx.scene.input.MouseEvent;

import javafx.scene.layout.GridPane;

import javafx.scene.layout.HBox;

import javafx.scene.layout.VBox;

import javafx.scene.paint.Color;

import javafx.scene.text.TextAlignment;

import javafx.stage.Stage;

public class Login extends Application {

final Label messageLabel = new Label("");

@Override

public void start(final Stage stage) {

Image image = new Image(getClass().getResourceAsStream("not.png"));

messageLabel.setGraphic(new ImageView(image));

messageLabel.setTextFill(Color.web("#0076a3"));

messageLabel.setTextAlignment(TextAlignment.JUSTIFY);

messageLabel.setWrapText(true);

messageLabel.setMaxWidth(300);

GridPane grid = new GridPane();

grid.setPadding(new Insets(0, 10, 10, 10));

grid.setVgap(5);

grid.setHgap(5);

Label userIdLabel = new Label("User Id");

GridPane.setConstraints(userIdLabel, 0, 0);

grid.getChildren().add(userIdLabel);

final TextBox userIdText = new TextBox();

userIdText.setText("1");

userIdText.setPromptText("Enter User id");

userIdText.setColumns(20);

GridPane.setConstraints(userIdText, 1, 0);

grid.getChildren().add(userIdText);

Label passwordLabel = new Label("Password");

GridPane.setConstraints(passwordLabel, 0, 1);

grid.getChildren().add(passwordLabel);


final PasswordBox passwordText = new PasswordBox();

passwordText.setText("seahorse");

passwordText.setPromptText("Enter password");

GridPane.setConstraints(passwordText, 1, 1);

grid.getChildren().add(passwordText);


final Button submit = new Button("Login");

submit.setOnMouseEntered(new EventHandler() {

@Override public void handle(MouseEvent e) {

submit.setScaleX(1.25);

submit.setScaleY(1.25);

}

});

submit.setOnMouseExited(new EventHandler() {

@Override public void handle(MouseEvent e) {

submit.setScaleX(1);

submit.setScaleY(1);

}

});

Button clear = new Button("Clear");

HBox hbButton = new HBox();

hbButton.setPadding(new Insets(5, 0, 0, 0));

hbButton.setSpacing(10);


hbButton.getChildren().addAll( submit,clear);


GridPane.setConstraints(hbButton, 1, 2);

grid.getChildren().add(hbButton);


submit.setOnAction(new EventHandler() {

@Override

public void handle(ActionEvent e) {


if (userIdText.getText() == null

userIdText.getText().isEmpty()

passwordText.getText() == null

passwordText.getText().isEmpty() ) {

messageLabel.setText("User Id and password can not be empty!");

return;

}

LoginService loginService = BeanHelper.getBean(LoginService.class);


boolean isAuthorized = false;

try {


isAuthorized = loginService.login(Integer.valueOf(userIdText.getText()).intValue() , passwordText.getText() );

} catch (Exception ex) {

messageLabel.setText(ExceptionUtil.handleException(ex).getMessage());

messageLabel.setTextFill(Color.rgb(210, 39, 30));

}


if (isAuthorized) {

CustomerSearch ll = new CustomerSearch();

ll.start(stage);

}

}

});


clear.setOnAction(new EventHandler() {

@Override

public void handle(ActionEvent e) {

userIdText.clear();

passwordText.clear();

messageLabel.setText("");

}

});



VBox vb = new VBox();

vb.setPadding(new Insets(10, 0, 0, 10));

vb.setSpacing(10);



vb.getChildren().addAll( messageLabel,grid);

final Scene scene = new Scene(vb, 300, 150);

stage.setScene(scene);

stage.setTitle("Login Page");


stage.setVisible(true);

}

public static void main(String[] args) {

SeaHorseStandaloneInitializer.initialize();

//weblogic (check port number)

PropertyHelper.getPropertyManager().setProperty(SeaHorseConstants.DEFAULT_REMOTE_SERVER_NAME, http://localhost:7001/remote/remote/);


Application.launch(args);

}

}



After running login , following login page is displayed






When login button is pressed,  login service on remote server will be called using the following code segment

LoginService loginService = BeanHelper.getBean(LoginService.class);


boolean isAuthorized = false;

try {

isAuthorized = loginService.login(Integer.valueOf(userIdText.getText()).intValue() , passwordText.getText() );

after successfull login, customer search page is called using the following code segment;


package com.seahorse.test.javafx;

import com.seahorse.bean.container.BeanHelper;
import com.seahorse.common.util.ExceptionUtil;
import com.seahorse.test.model.Customer;
import com.seahorse.test.service.CustomerService;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextBox;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class CustomerSearch {

    final TextBox searchText = new TextBox();
    private TableView tableView;
    private ObservableList tableItems;

    public static class CustomerFX {

        private IntegerProperty customerId;

        public void setCustomerId(Integer value) {
            customerIdProperty().set(value);
        }

        public Integer getCustomerId() {
            return customerId.get();
        }

        public IntegerProperty customerIdProperty() {
            if (customerId == null) {
                customerId = new IntegerProperty();
            }
            return customerId;
        }
        private StringProperty name;

        public void setName(String value) {
            nameProperty().set(value);
        }

        public String getName() {
            return name.get();
        }

        public StringProperty nameProperty() {
            if (name == null) {
                name = new StringProperty();
            }
            return name;
        }
        private StringProperty surname;

        public void setSurname(String value) {
            surnameProperty().set(value);
        }

        public String getSurname() {
            return surname.get();
        }

        public StringProperty surnameProperty() {
            if (surname == null) {
                surname = new StringProperty();
            }
            return surname;
        }
    }

    public void start(Stage primaryStage) {

        primaryStage.setWidth(500);
        primaryStage.setHeight(400);
        primaryStage.setTitle("Customer Search Page");

        VBox vb = new VBox();
        vb.setPadding(new Insets(10, 10, 10, 10));
        vb.setSpacing(10);

        Scene scene = new Scene(vb, 500, 400, Color.BEIGE);

        //   searchText.setPromptText("Enter Customer id");  does not work!!
        searchText.setColumns(20);


        Label searchLabel = new Label("Search:");

        HBox searchBox = new HBox();
        searchBox.setSpacing(5);
        searchBox.setAlignment(Pos.CENTER_LEFT);

        searchBox.getChildren().addAll(searchLabel, searchText);


        final ChoiceBox cb = new ChoiceBox(FXCollections.observableArrayList(
                "Customer ID", "First Name", "Last Name"));

        cb.getSelectionModel().selectedIndexProperty().addListener(new ChangeListener() {

            public void changed(ObservableValue ov, Number value, Number new_value) {

                if (new_value.intValue() == 0) {
                    searchText.clear();
                    //searchText.setPromptText("Enter Customer id");   // does not workkkk!!!
                } else if (new_value.intValue() == 1) {
                    searchText.clear();
                    //searchText.setPromptText("Enter First Name");
                } else {
                    searchText.clear();
                    //searchText.setPromptText("Enter Last Name");
                }
            }
        });

        Label criteriaLabel = new Label("Using:");

        HBox criteriaBox = new HBox();
        criteriaBox.setSpacing(5);
        criteriaBox.setAlignment(Pos.CENTER_LEFT);

        criteriaBox.getChildren().addAll(criteriaLabel, cb);

        Button searchButton = new Button();
        searchButton.setText("Search");

        Button btnClear = new Button();
        btnClear.setText("Clear");

        btnClear.setOnAction(new EventHandler() {

            public void handle(ActionEvent event) {
                tableItems.clear();
                cb.getSelectionModel().selectFirst();
            }
        });

        HBox hbButtonBox = new HBox();
        hbButtonBox.setPadding(new Insets(5, 0, 0, 0));

        hbButtonBox.setSpacing(10);

        hbButtonBox.getChildren().addAll(searchBox, criteriaBox, searchButton, btnClear);

        searchButton.setOnAction(new EventHandler() {

            public void handle(ActionEvent event) {

                btnSearchPressed(cb.getSelectionModel().getSelectedIndex(), searchText);
            }
        });

        primaryStage.setScene(scene);
        primaryStage.setVisible(true);

        tableItems = FXCollections.observableArrayList();

        tableView = new TableView(tableItems);

        TableColumn col1 = new TableColumn("Cust ID");
        TableColumn col2 = new TableColumn("First Name");
        TableColumn col3 = new TableColumn("Last Name");

        col1.setProperty("customerId");
        col2.setProperty("name");
        col3.setProperty("surname");

        tableView.getColumns().setAll(col1, col2, col3);

        vb.getChildren().addAll(hbButtonBox, tableView);

    }

    public void btnSearchPressed(int selection, TextBox searchText) {

        CustomerService customerService = BeanHelper.getBean(CustomerService.class);

        List customers = null;

        try {

            if (selection == 0) {

                if (searchText.getText() == null || searchText.getText().isEmpty()) {
                    tableItems.clear();
                    return;
                }
                Customer cust = customerService.getCustomer(Integer.valueOf(searchText.getText()).longValue());

                List list = new ArrayList();
                list.add(cust);

                customers = list;
            } else if (selection == 1) {
                customers = customerService.getCustomersByFirstName(searchText.getText());
            } else {
                customers = customerService.getCustomersByLastName(searchText.getText());
            }

            fillTable(customers);

        } catch (Exception ex) {
            tableItems.clear();
            Logger.getLogger(CustomerSearch.class.getName()).log(Level.SEVERE, null, ExceptionUtil.handleException(ex).getMessage());
        }

    }

    public void fillTable(List customers) {

        tableItems.clear();

        if (customers == null || customers.isEmpty()) {
            return;
        }

        ObservableList newItems = FXCollections.observableArrayList();

        for (int i = 0; i < customers.size(); i++) {

            CustomerFX p = new CustomerFX();

            Customer customer = customers.get(i);

            p.setName(customer.getName());
            p.setSurname(customer.getSurname());
            p.setCustomerId(Integer.valueOf((int) customer.getCustomerId()));

            newItems.add(p);
        }

        tableView.getItems().setAll(newItems);
    }
}






after successfull login, customer search page is displayed;  you can search customers according to customer id, name and last name.











Labels: , , , ,

Friday, June 10, 2011

Seahorse annotation driven RIA application development framework version 1.1 is released

Seahorse is an annotation driven framework that provides solutions for the model and controller layer of MVC based multiple rich internet applications (RIAs). Seahorse goals to provide all required functionality such as annotation driven dependency injection container (DIC), transaction management, persistency, caching, scheduling, authentication, remoting etc. to develop MVC based RIA applications. Seahorse can be used in distributed and collocated application architectures to develop Ajax based web applications and java rich client applications using JavaFX and Swing. Seahorse provides transparent remoting services to access to server side from rich client applications.



Followings are benefits of using Seahorse framework;

1. Declarative development environment for rapid application development

2. End to End solutions for the model and controller layer for the RIA applications

3. Annotation driven IOC container to easily configure and bind POJO beans

4. Declarative remote access and authentication for multiple rich clients

5. Declarative Transaction Management

6. Declarative server and client side caching

7. Declarative scheduling

8. JDBC abstraction layer that provides less coding and more robust development

9. Zero implementation to call stored procedures by providing declarative persistency

10. Highly customizable framework that almost you can change any framework implementation with the same approach that is used for configure applications



SeaHorse framework 1.1 tutorial, source code , binaries and sample project added to google code and can be downloaded from the following link : http://code.google.com/p/seahorse-ria-framework/

Labels:

Thursday, July 09, 2009

using jaxws 2.1 for exposing web services

jaxWS 2.1 simplifies web service development for java based applications. It is very easy to expose your pojo service classes as web services just using web service annotations.

Just put @WebService annotation on your service class, that's all . You can also restrict number of methods to be exposed using @WebMethod annotation on methods of exposed service class.

For the GlassFish V2 you dont have to add anything to web.xml file for the web services. All of required definitions will be added by GlassFish during the deployment. On the other hand , for the tomcat, you have to add listener definitions into web.xml file to run web services.

During the deployement all classes containing web service annotations are scanned by AS and required web service classes are generated using wsgen tool. For this process you need JDK that contains wsgen and apt tools. If you specified jre you will get the following error message during deployment.

com.sun.xml.ws.model.RuntimeModelerException: runtime modeler error: Wrapper class {0} is not found. Have you run APT to generate them?

Labels:

Tuesday, April 14, 2009

SeaHorse Framework Version 1.0 is ready

I have developed a new annotation driven framework called as SeaHorse framework.

SeaHorse is a annotation driven framework that aims to simplify java development and increase the productivity for the model layer issues of the MVC (Model View Controller) based java applications. To simplify development seahorse framework provides declarative programming environment using annotations. With declarative programming developers describe desired result of the program without explicitly writing codes that need to be carried out to achieve the results. You can still use imperative development with SeaHorse framework. You can also use declarative and imperative development together.

To get seahorse 1.0 click the following link http://sourceforge.net/projects/jseahorse/

Thursday, August 10, 2006

POJO Based Development

POJO is an acronym for Plain Old Java Object. Nowadays, in java community , POJO based development approach is getting more attention by java developers. So, you may ask yourself what is a pojo object and why its gaining more attention by developers. POJO object is an ordinary java bean, no more no less. If you developed applications using EJB technology, that is a part of J2EE technology stack. you know creating an entity bean is a complex task. when you develop an enterprise application using a framework such as EJB, domain classes in your application have to extend or implement a framework classes. If you have a class that implements or extends any class it is difficult to reuse that class. For example, if a class have to extend a framework class to get some framework services that class never extend any class in our application. Reusing that classes in others parts of applications becomes difficult.Also, when your classes extends or implements framework classes, your domain objects becomes tightly coupled to the framework. As a result of tightly coupling it is hard to test domain objects outside of framework. If you used EJB for persistency in your project, for an entity object , you can only run and test your object inside of an J2EE container. Outside of EJB container your object will be useless. Coupling is a very bad thing for an application. In the case of EJB based application your application are coupled to EJB container.Every application has coupling. Loose coupling gives us a lot of flexibility in reusing,unit testing,deployment and tuning. When you develop an application using a framework a degree of coupling between your application and framework is important. More coupling shows that your domain objects would be more complex, hard to manage and test as a result your application would be complex application. Less coupling shows that your domain objects would be simple objects(POJOs) , easy to manage and test as a result your application would be simple application. If your application simple it is easy to maintain and testing.

There are a common complaints about java development that learning curve is long and coding with java is difficult and applications developed using java are too complex. Java as a programming language is very powerful and simple. J2EE is a standart java based enterprise application development technology for the web based java development. J2EE technology is a well known and dominant framework in java community also dominated by the Sun. J2EE technology stack contains technologies such as EJB, Servlet, JSPs,JNDI and other technologies. J2EE is a heavyweight approach to the web based development because of EJB technology is a distributed application architecture. Developing applications using distributed application is a complex task. If your application is a distributed application, any object in your application may be reside on any any machine in the network. Solving problems using a distributed architecture results with a complex solution. Although your problem domain is simple your application would be complex because of based complex architectre . Developing web applications using EJB are complicated. If you decide to use EJB in our project you also decided your application architecture probably be a distributed application architecute.

If we ask question again , why applications developed using java are complex? The main reason is EJB a complex architecture and generally results with a complex solution(application).

There are a lot of new frameworks based on java technology. Most of them lightweight frameworks.

POJO based development aims to simplify application development and unit testing and allows to develop loosely coupled applications. J2EE is dominant framework in java community,