Flex Client Applications with Spring/JavaEE, Web Services and Flex Remoting

From the lessons learned from such experiences, today annotations gains popularity over xml and light weight and POJO containers such as Spring and JavaEE5 make things simpler.

In our Eclipse Democamp presentation we aimed to show how simple things can be done and since this is the era of high banthwith and rich client interfaces how rich our client side can be.

Domain model

In our demo we kindly ask our audience to form a domain model for us to code. The example domain consists of 3 objects; an account, a branch which has accounts and a customer which has accounts.

Domain driven development gives you the opportunitiy to work with objects and directly model your real life problems to them. One of the first problem you face when start dealing with objects is how to persist them. Databases have been around for many years even longer than most of the programming languages we use today. However, the database models usually are not very compatible with the domain models which are built on objects. Unless you want to use a object oriented database mocel such as DB4o, you need to use a persistance tool wihich will map your domain model to a database and will provide easy querying functions. SUN microsystem has forseen the importance and rise of ORM tools and let us use the Java Persistance API. With JPA we can easily change the ORM layer and wont expose vendor specific code in to our software. However, each vendor, such as Hibernate in our example, provides an extended set of tools compared to JPA.

Hibernate is a mature tool which is very integrated with Eclipse and the annotations let you to set up everything very easily. Each object we want to persist is named as an entity so we mark them with the annotation @entity. JPA allows us to choose how the sequence generator will generate the uniuque ids.

@Entity           //1      

@Table(name = "BRANCH")              //2

@SequenceGenerator(name = "BRANCH_ID", sequenceName = "my_sequence") //3

public class Branch {

            @Id      //4

            @GeneratedValue(strategy = GenerationType.AUTO, generator = "BRANCH_ID")

            private Long id;

            private String name;

            private String address;

            private String phoneNumber;

            @OneToMany(mappedBy = "branch", cascade = CascadeType.ALL)        //4

            private Set accounts = new HashSet(0);

            //getters & setters...

}

In our code number (1) marks the class as entity which tells JPA to persist this entity. (2)optional, gives the name of the table where the entity should be persisted. (3)optional, determines the unique identifier creation strategy and our generator name.

Our entity code is quite simple but since we are using objects, we need to interact with other objects. (4) Again JPA offers annotations to mark relations between entities. To add an relatinal account reference in our branch, we need to type the relation type. Set of accounts are mapped by branch. Since one branch is mapped with many accounts this relation is oneToMany. Cascade type determines the strategy this entity's life when the corresponding entity in relation is deleted.

Since Branch entity is in relation with Account entity lets examine the other entity's code.

@Entity           //1

@Table(name = "ACCOUNT")

@SequenceGenerator(name = "ACCOUNT_ID", sequenceName = "my_sequence")

public class Account {

            @Id

            @GeneratedValue(strategy = GenerationType.AUTO, generator = "ACCOUNT_ID")

            private Long id;

            private String accountNumber;

            private Double availableAmount;

            private Double overdraftAmount;

            private String currency;

            @ManyToOne(fetch = FetchType.LAZY)     //2

            @JoinColumn(name = "BRANCH", nullable = false)           //3

            private Branch branch;

            @ManyToOne(fetch = FetchType.LAZY)     //4

            @JoinColumn(name = "CUSTOMER", nullable = false)      

            private Customer customer;

            //getters & setters

}

In Account class number (1) again shows the class is an entity and needs to be persisted with the given table name and sequence strategy. (2)  Account class has many to one relation with the branch class since one branch has many accounts. (3)optional, determines the name of the joim column and if the relation can be persisted as null.

(4) shows Account entity has a similar relation like branch with the customer entity.

Please refer to the code attachments or download the code from cvs for examining the full codes of all three entity.

As we finish building our domain model, we can let hibernate to create our database model, again hibernate allows many customization table structures and persisting data, you may just refer to hibernate documentation for further details.

To configure hibernate, entities should be add to hibenate-config.xml among other database specific configurations.

To build the database from scratch for the given model we need to type an ant script. The ant script will use the hibernate-config.xml for the connection and dialect Properties of the database and entity mappings for design of the database and its relations.

Since The domain Model and persistance layer is ready to use we need Data Access Objects and backend services for our clients to use.

Spring

J2EE was revolutionary and gain popularity easily among clients and vendors. However, due to the complex structure of j2EE developers had difficulty from coding to deploying. The idea of Spring came to simplify enterprise java. Spring offers easy of use and can be configured easily. Later, Spring is followed by JavaEE5, with EJB3 and JPA. The main advantage of EJB3, the annotations has also been implemented by spring lately. However in our example we use the tradional configuration way.

Building the application in layers gives the opportunity of loosely coupling and flexibility. Using Data Access Objects hides the database related code from business code. In our DAOs we will use Spring DAO support. In previous part we designed our entities so the code below will do the data access operations.

public class BranchDAO extends HibernateDaoSupport implements IBranchDAO {

            @SuppressWarnings("unchecked")

            @Override

            public List findByExample(Branch exampleInstance) {

                        return getHibernateTemplate().findByExample(exampleInstance);

            }

            @Override

            public Branch findById(Serializable id) {

                        return (Branch) getHibernateTemplate().load(Branch.class, id);

            }

            @Override

            public Branch save(Branch entity) {

                        getHibernateTemplate().saveOrUpdate(entity);

                        return entity;

            }

}

The DAO classes are ready we need to specify them as Spring beans. To achieve this we type our data access related configuration to webAppContext.xml.

The entity and DAO classes are ready to use by the business layer. Our business layer will be serving both as web service and blaze remoting.

@WebService(targetNamespace = "http://service.workshop.flexjava.org") //1

public interface BankService {

            public Customer findCustomer(@WebParam(name = "customerNumber") String customerNumber); //2

            public void addCash(@WebParam(name = "accountId") Long accountId, @WebParam(name = "amount") Double amount);

            public void drawCash(@WebParam(name = "accountId") Long accountId, @WebParam(name = "amount") Double amount);

            public void transferCash(@WebParam(name = "senderAccountId") Long senderAccountId,

                                   @WebParam(name = "receiverAccountNumber") String receiverAccountNumber, @WebParam(name = "amount") Double amount);

}

To enable our business methods as webservices we will use CFX. CFX offers good integration with spring and also supports annotations. (1) marks our class as the webservice class, this class will form our WSDL for the client. (2) is the first of our web service methods, WebParam annotation marks the parameter expected from the web service request. Each method we enable as web method we need to mark our expected parameters with WebParam annotation.

public class BankServiceImpl implements BankService { //1

            private IAccountDAO accountDAO;          //2

            private IBranchDAO branchDAO;              //3

            public ICustomerDAO getCustomerDAO() {

                        return customerDAO;

            }

            public void setCustomerDAO(ICustomerDAO customerDAO) {

                        this.customerDAO = customerDAO;

            }

            @Override

            public Customer findCustomer(String customerNumber) {

                        Customer customer = new Customer();

                        customer.setCustomerNumber(customerNumber);

                        List resultList = customerDAO.findByExample(customer);

                        if (resultList.isEmpty()) {

                                   return null;

                        } else {

                                   return resultList.get(0);

                        }

            }

            ....

(1) We code our Service implementation on the interface we prepared before. One of the very nice features of Spring is dependancy injection which is also known as inversion of control. Before DI, JNDI lookups were the only way to load resources, which cause untidy coding and difficult in testing. Our business service classes will need the related DAOs but initialising and loading the DAOs is not actually their job.  (2) and (3) is the references where aour spring dao beans will be injected. Unlike EJB3 we need public getter/setter to inject those resources via spring. To finish configuring injection process we need to add those to webAppContext.xml.

            implementorClass="org.flexjava.workshop.service.BankService"

            address="/BankOperations" />

This configuration lets us to inject the needed DAOs into our business classes. With Spring 2.5 and JavaEE5 you can achieve this with annotations.

Our methods in business service bean are marked transactional. First we want to use our service methods as web services. We can see the advantage of using the interfaces since all we need to do is to mark the methods with the approciate parameters and add the CXF configuration xml. With JavaEE5 the builtin web service engine can be used.

Web Client

Our entities, data access layer and business layer are complete. So now lets move to the client side to code our web client.

 In 1996 when Java applets was first ıntroduced everyone was so impressed by the magic of the dancing duke logo.Applets became popular but in time they face serious problems; low bandthwiths, difficulty of installiation of JRE for  non experienced users, compability problems cause made developers gave up on applets.

As java got stronger on server side, it has lost popularity on rich client side. Later we were introduced by the AJAX which was actually built on an old feature of browsers which was never used until that time. AJAX was just like teaching an old dog new tricks. It was painful, hard to debug and not fully cross-browser compatible. Many frameworks pop out in time, such as GWT, to make javascript programming easier and offer richer user experience but still unlike applets they were all under the limitations of HTML.

Adobe's Flex is another alternative to Rich Client platform. It runs in Flash runtime which is stable and is widely installed  in many clients. Unlike Java applets, if the client does not have the runtime installed, Flash runtime is simple to install even for the most inexperienced user. Flex SDK was open sourced by version 2. You can download, install and compile your code for free. However Adobe also offers a licenced plugin for Eclipse.

Flex MXML classes are pure XML which can include the actionscript codes. An application starts  and end with tags. There are many built in components like buttons, grids, data tables, video containers.. Each components can be placed and initialised by MXML code although that can also be done by actionscript.    

In this example there are 2 buttons which has exactly same Properties and calling the same function when they are clicked. The only difference is their x axis value and how they are initialised.

This xml structure allows seperation of visual components from the code. However you can still access the components from code by their ids any time. Flex also offers a css based style management which allows to change the style even the software is running.

Flex is an event driven platform. Every interaction is an event, you can register event listeners to components, containers or even to the application. Just like JavaScript click is an event in Flex, but you also have before click, after click, double click.. You can listen and capture any event you can imagine of.

In Flex user interface can be organised by “states”. A state is the screen layout and components for that action. A state can be used to form a new screen layout when a button is clicked, like opening a form. Other child states can be used to enable, disable or remove unused form components from the interface.

            INVEST_MONEY" basedOn="CUSTOMER_DETAIL">

            DRAW_MONEY" basedOn="CUSTOMER_DETAIL">

States are hierachical, so remember anything you added will also appear on child states, or anything will remove will also disappear from child states. States are also an easy way to use Flex's Flash based effect library. You can easily add enter and exit effects for the state or add, remove effects for the components of that state, just like in the previous example.

Variables can be bindable in Flex, which enables to use a variable as data provider of a visual component such as a table. For example a bindable array can be data provider of a data grid which will fill the data grid automatically and will also update the array when the data on the data grid is changed.

      myGrid" editable="true" dataProvider="{myCollection}" itemFocusOut="showName()">           

                  private var myCollection:ArrayCollection  = new ArrayCollection([{firstName: 'Murat', lastName: 'Yener'}, {firstName: 'Yunus', lastName: 'Bayraktar'}]);

                  private function showName():void{

                        Alert.show(myGrid.selectedItem.firstName+" "+myGrid.selectedItem.lastName);

                  }

            ]]>

This example binds the arrayCollection with the dataGrid and adds several event listeners, the itemFocusOut event shows how the data is syncronised.

Web Services and Remoting

Flex offers to communicate with the server in several ways such as, http request, webservices and remoting. We will cover the last two in this article. We already enabled web services on the client side so all we need to do is type the wsdl adress in our flex application.

            findCustomer" result="Alert.show('Customer Found'); showCustomerDetails();" fault="Alert.show('error')">

...

      private function showPartyList(res:ResultEvent):void{

            if (res.result!=null){

                                   Alert.show( res.result.name );

            }

      }

Our request to send is an event and the asyncronous response which will be received is also an event. To capture that response we register an event listener. Flex uses Dynamic Objects which are not strongly casted, you can even add a new field to the received object. Dynamic objects very easy and fast to implement but since they must be used carefully.

Remoting is a faster and more efficient way to communicate with the server. Until last January remoting was an expensive option under the name of Live Services. Adobe open sourced a subset of live services under the name of BlazeDS which is completely free. Just as Java remoting the Flex client can call any of the server side methods in a native way and transfer seriliazed objects. To enable Blaze remoting, several xml config files added to the server side. This config files can be found under flex directory under resources. You may freely copy these files into your application and change them according to your sunction and service names. To enable our server to load up our blaze configuration, following line must be added to web.xml.

            flex.messaging.HttpFlexSession

            MessageBrokerServlet

            flex.messaging.MessageBrokerServlet

                   services.configuration.file

                   /WEB-INF/flex/services-config.xml

                   flex.write.path

                   /WEB-INF/flex

            1

Now our Spring bean  is also available for remoting. To start using remoting we must have an equivalent of the entities of the server side on the client side. To show an example below there is the ActionScript remote class equivalent of our Branch entity.

package org.flexjava.workshop.entity

{

      import mx.collections.ArrayCollection;

      [RemoteClass(alias="org.flexjava.workshop.entity.Customer")]

      public class Customer

      {

            public var id:Number;

            public var name:String;

            public var customerNumber:String;

            public var address:String;

            public var tckNumber:String;

            public var vkNumber:String;

            public var accounts:ArrayCollection;

      }

}

To use remoting on the previous web service call example;

      http://localhost:8080/WorkshopJava/messagebroker/amf" />

To call call remote findCustomer method we can just use “rObj.findCustomer” any response will trigger showCustomerDetails method, and the response will have a concrete Customer object. These are the basic communication examples.However, in the code example given with the CD or downloaded from CVS, you will find more advanced 2 actionscript classes which are coded to organise method calls. These classes are responsable to register the reponse listeners and to initialise your server address for making your life easier.

BankWebService AS class will load the apprciate wsdl and register your call with the given listener each time you call for a webservice.

      public class BankWebService extends WebService

      {

            public function BankWebService() {

                  this.useProxy = false;

                  this.loadWSDL("http://localhost:8080/WorkshopJava/BankOperations?wsdl");

            }

            private function setOperationListener(operation:AbstractOperation, listener:Function):void {

                  if(!operation.hasEventListener(ResultEvent.RESULT)) {

                        operation.addEventListener(ResultEvent.RESULT, listener);

                  }

            }

            public function findCustomer(listener:Function, customerNumber:String):void {

                  var operation:AbstractOperation = getOperation("findCustomer");

                  setOperationListener(operation, listener);

                  operation.send(customerNumber);

            }

This service can be used as simple as like this;

private function findCustomer():void {

                        Alert.show(txtCustomerNumber.text);

                        bankService.findCustomer(findCustomerListener, txtCustomerNumber.text);

                  }

In this method we get the value of  txtCustomerNumber.text and call the methos with that parameter. The response will trigger findCustomerListener function.

To use the same example with remoting, we use the remoting equivalents of this class which is named, BankService.

      public class BankService extends RemoteObject

      {

            public function BankService() {

                  super("BankDestination");

                  endpoint = "http://localhost:8080/WorkshopJava/messagebroker/amf";

            }

            private function setOperationListener(operation:AbstractOperation, listener:Function):void {

                  if(!operation.hasEventListener(ResultEvent.RESULT)) {

                        operation.addEventListener(ResultEvent.RESULT, listener);

                  }

            }

            public function findCustomer(listener:Function, customerNumber:String):void {

                  var operation:AbstractOperation = getOperation("findCustomer");

                  setOperationListener(operation, listener);

                  operation.send(customerNumber);

            }

This service can be used in a similar way;

                  private function findCustomer():void {

                        Alert.show(txtCustomerNumber.text);

                        bankService.findCustomer(findCustomerListener, txtCustomerNumber.text);

                  }

The response listener will receive a customer object.

private function findCustomerListener(event:ResultEvent):void {

                        if (event.result == null) {

                             Alert.show("Customer not exist with the given number!");

                             return;

                        }

                        customer = Customer(event.result);

                        if (this.currentState == "CUSTOMER_DETAIL"

                             || this.currentState == "DRAW_MONEY"

                             || this.currentState == "INVEST_MONEY"

                             || this.currentState == "TRANSFER_MONEY") {

                             this.currentState = "CUSTOMER_DETAIL";

                             bindData();

                        } else {

                             this.currentState = "CUSTOMER_DETAIL";

                        }

                  }

In this example, which is the same as the code given with the cd, we change our current state and bind our new received data if needed.

Conclusion

Eclipse is a great platform for development with its unlimited plugins and extentions.Although this example uses so little of its capabilities we tried to show how easy your development process can be with the approciate tools and with some addition from Flex, your client software will be richer and more trendy.

 

“Everything should be made as simple as  possible, but not simpler” software projects tend to fail because usually they are designed in a complex and over engineered way. Internet is full of articles on how projects become over complicated and fail. J2EE was a very promising platform with new set of  tools to make developer's life easier. XML configuration files were also introduced for same reason, ease of configuration.  However J2EE failed to simplify things in many Aspects.

From the lessons learned from such experiences, today annotations gains popularity over xml and light weight and POJO containers such as Spring and JavaEE5 make things simpler.

In our Eclipse Democamp presentation we aimed to show how simple things can be done and since this is the era of high banthwith and rich client interfaces how rich our client side can be.

 

In our demo we kindly ask our audience to form a domain model for us to code. The example domain consists of 3 objects; an account, a branch which has accounts and a customer which has accounts.

 

Domain driven development gives you the opportunitiy to work with objects and directly model your real life problems to them. One of the first problem you face when start dealing with objects is how to persist them. Databases have been around for many years even longer than most of the programming languages we use today. However, the database models usually are not very compatible with the domain models which are built on objects. Unless you want to use a object oriented database mocel such as DB4o, you need to use a persistance tool wihich will map your domain model to a database and will provide easy querying functions. SUN microsystem has forseen the importance and rise of ORM tools and let us use the Java Persistance API. With JPA we can easily change the ORM layer and wont expose vendor specific code in to our software. However, each vendor, such as Hibernate in our example, provides an extended set of tools compared to JPA.

Hibernate is a mature tool which is very integrated with Eclipse and the annotations let you to set up everything very easily. Each object we want to persist is named as an entity so we mark them with the annotation @entity. JPA allows us to choose how the sequence generator will generate the uniuque ids.

 

@Entity           //1      

@Table(name = "BRANCH")              //2

@SequenceGenerator(name = "BRANCH_ID", sequenceName = "my_sequence") //3

public class Branch {

 

            @Id      //4

            @GeneratedValue(strategy = GenerationType.AUTO, generator = "BRANCH_ID")

            private Long id;

            private String name;

            private String address;

            private String phoneNumber;

            @OneToMany(mappedBy = "branch", cascade = CascadeType.ALL)        //4

            private Set<Account> accounts = new HashSet<Account>(0);

            //getters & setters...

}

 

In our code number (1) marks the class as entity which tells JPA to persist this entity. (2)optional, gives the name of the table where the entity should be persisted. (3)optional, determines the unique identifier creation strategy and our generator name.

 

Our entity code is quite simple but since we are using objects, we need to interact with other objects. (4) Again JPA offers annotations to mark relations between entities. To add an relatinal account reference in our branch, we need to type the relation type. Set of accounts are mapped by branch. Since one branch is mapped with many accounts this relation is oneToMany. Cascade type determines the strategy this entity's life when the corresponding entity in relation is deleted.

Since Branch entity is in relation with Account entity lets examine the other entity's code.

 

@Entity           //1

@Table(name = "ACCOUNT")

@SequenceGenerator(name = "ACCOUNT_ID", sequenceName = "my_sequence")

public class Account {

 

            @Id

            @GeneratedValue(strategy = GenerationType.AUTO, generator = "ACCOUNT_ID")

            private Long id;

            private String accountNumber;

            private Double availableAmount;

            private Double overdraftAmount;

            private String currency;

            @ManyToOne(fetch = FetchType.LAZY)     //2

            @JoinColumn(name = "BRANCH", nullable = false)           //3

            private Branch branch;

            @ManyToOne(fetch = FetchType.LAZY)     //4

            @JoinColumn(name = "CUSTOMER", nullable = false)      

            private Customer customer;

            //getters & setters

}

 

In Account class number (1) again shows the class is an entity and needs to be persisted with the given table name and sequence strategy. (2)  Account class has many to one relation with the branch class since one branch has many accounts. (3)optional, determines the name of the joim column and if the relation can be persisted as null.

(4) shows Account entity has a similar relation like branch with the customer entity.

 

Please refer to the code attachments or download the code from cvs for examining the full codes of all three entity.

 

As we finish building our domain model, we can let hibernate to create our database model, again hibernate allows many customization table structures and persisting data, you may just refer to hibernate documentation for further details.

To configure hibernate, entities should be add to hibenate-config.xml among other database specific configurations.

        <mapping class="org.flexjava.workshop.entity.Account" />

        <mapping class="org.flexjava.workshop.entity.Branch" />

        <mapping class="org.flexjava.workshop.entity.Customer" />

 

To build the database from scratch for the given model we need to type an ant script. The ant script will use the hibernate-config.xml for the connection and dialect Properties of the database and entity mappings for design of the database and its relations.

 

        name="schemaexport" >

              id="toolslib">

                    dir="${libdir}">

                          name="**/*.jar" />

                   

                    location="build/classes" />

             

              name="hibernatetool" classname="org.hibernate.tool.ant.HibernateToolTask" classpathref="toolslib" />

              destdir="bin">

                    configurationfile="resources/hibernate.cfg.xml" />

                    export="true" drop="false" update="true" outputfilename="schema-create.ddl" />

             

       

 

Since The domain Model and persistance layer is ready to use we need Data Access Objects and backend services for our clients to use.

 

J2EE was revolutionary and gain popularity easily among clients and vendors. However, due to the complex structure of j2EE developers had difficulty from coding to deploying. The idea of Spring came to simplify enterprise java. Spring offers easy of use and can be configured easily. Later, Spring is followed by JavaEE5, with EJB3 and JPA. The main advantage of EJB3, the annotations has also been implemented by spring lately. However in our example we use the tradional configuration way.

 

Building the application in layers gives the opportunity of loosely coupling and flexibility. Using Data Access Objects hides the database related code from business code. In our DAOs we will use Spring DAO support. In previous part we designed our entities so the code below will do the data access operations.

 

public class BranchDAO extends HibernateDaoSupport implements IBranchDAO {

 

            @SuppressWarnings("unchecked")

            @Override

            public List<Branch> findByExample(Branch exampleInstance) {

                        return getHibernateTemplate().findByExample(exampleInstance);

            }

 

            @Override

            public Branch findById(Serializable id) {

                        return (Branch) getHibernateTemplate().load(Branch.class, id);

            }

 

            @Override

            public Branch save(Branch entity) {

                        getHibernateTemplate().saveOrUpdate(entity);

                        return entity;

            }

}

 

The DAO classes are ready we need to specify them as Spring beans. To achieve this we type our data access related configuration to webAppContext.xml.

      <bean id="hibernateDaoSupport" class="org.springframework.orm.hibernate3.support.HibernateDaoSupport" abstract="true">

            <property name="sessionFactory" ref="sessionFactory" />

      bean>

 

      <bean id="accountDAO" class="org.flexjava.workshop.dao.AccountDAO" parent="hibernateDaoSupport" />

      <bean id="branchDAO" class="org.flexjava.workshop.dao.BranchDAO" parent="hibernateDaoSupport" />

      <bean id="customerDAO" class="org.flexjava.workshop.dao.CustomerDAO" parent="hibernateDaoSupport" />

 

The entity and DAO classes are ready to use by the business layer. Our business layer will be serving both as web service and blaze remoting.

 

@WebService(targetNamespace = "http://service.workshop.flexjava.org") //1

public interface BankService {

 

            public Customer findCustomer(@WebParam(name = "customerNumber") String customerNumber); //2

 

            public void addCash(@WebParam(name = "accountId") Long accountId, @WebParam(name = "amount") Double amount);

 

            public void drawCash(@WebParam(name = "accountId") Long accountId, @WebParam(name = "amount") Double amount);

 

            public void transferCash(@WebParam(name = "senderAccountId") Long senderAccountId,

                                   @WebParam(name = "receiverAccountNumber") String receiverAccountNumber, @WebParam(name = "amount") Double amount);

 

}

 

To enable our business methods as webservices we will use CFX. CFX offers good integration with spring and also supports annotations. (1) marks our class as the webservice class, this class will form our WSDL for the client. (2) is the first of our web service methods, WebParam annotation marks the parameter expected from the web service request. Each method we enable as web method we need to mark our expected parameters with WebParam annotation.

 

public class BankServiceImpl implements BankService { //1

 

            private IAccountDAO accountDAO;          //2

            private IBranchDAO branchDAO;              //3

            public ICustomerDAO getCustomerDAO() {

                        return customerDAO;

            }

 

            public void setCustomerDAO(ICustomerDAO customerDAO) {

                        this.customerDAO = customerDAO;

            }

 

            @Override

            public Customer findCustomer(String customerNumber) {

                        Customer customer = new Customer();

                        customer.setCustomerNumber(customerNumber);

                        List<Customer> resultList = customerDAO.findByExample(customer);

                        if (resultList.isEmpty()) {

                                   return null;

                        } else {

                                   return resultList.get(0);

                        }

            }

            ....

(1) We code our Service implementation on the interface we prepared before. One of the very nice features of Spring is dependancy injection which is also known as inversion of control. Before DI, JNDI lookups were the only way to load resources, which cause untidy coding and difficult in testing. Our business service classes will need the related DAOs but initialising and loading the DAOs is not actually their job.  (2) and (3) is the references where aour spring dao beans will be injected. Unlike EJB3 we need public getter/setter to inject those resources via spring. To finish configuring injection process we need to add those to webAppContext.xml.

 

      <jaxws:endpoint id="bankOps" implementor="#bankBean"

            implementorClass="org.flexjava.workshop.service.BankService"

            address="/BankOperations" />

 

      <bean id="bankBean" class="org.flexjava.workshop.service.BankServiceImpl">

            <property name="accountDAO" ref="accountDAO"/>

            <property name="branchDAO" ref="branchDAO"/>

            <property name="customerDAO" ref="customerDAO"/>

      bean>

 

This configuration lets us to inject the needed DAOs into our business classes. With Spring 2.5 and JavaEE5 you can achieve this with annotations.

 

Our methods in business service bean are marked transactional. First we want to use our service methods as web services. We can see the advantage of using the interfaces since all we need to do is to mark the methods with the approciate parameters and add the CXF configuration xml. With JavaEE5 the builtin web service engine can be used.

 

Our entities, data access layer and business layer are complete. So now lets move to the client side to code our web client.

 

In 1996 when Java applets was first ıntroduced everyone was so impressed by the magic of the dancing duke logo.Applets became popular but in time they face serious problems; low bandthwiths, difficulty of installiation of JRE for  non experienced users, compability problems cause made developers gave up on applets.

As java got stronger on server side, it has lost popularity on rich client side. Later we were introduced by the AJAX which was actually built on an old feature of browsers which was never used until that time. AJAX was just like teaching an old dog new tricks. It was painful, hard to debug and not fully cross-browser compatible. Many frameworks pop out in time, such as GWT, to make javascript programming easier and offer richer user experience but still unlike applets they were all under the limitations of HTML.

 

Adobe's Flex is another alternative to Rich Client platform. It runs in Flash runtime which is stable and is widely installed  in many clients. Unlike Java applets, if the client does not have the runtime installed, Flash runtime is simple to install even for the most inexperienced user. Flex SDK was open sourced by version 2. You can download, install and compile your code for free. However Adobe also offers a licenced plugin for Eclipse.

 

Flex MXML classes are pure XML which can include the actionscript codes. An application starts  and end with tags. There are many built in components like buttons, grids, data tables, video containers.. Each components can be placed and initialised by MXML code although that can also be done by actionscript.

 

 

  xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" applicationComplete="init()">

        x="29" y="59" label="Button" id="button1" click="buttonClick(event)"/>

       

           

                  import mx.controls.Alert;

                  import mx.collections.ArrayCollection;

                  [Bindable]-->

                  private var myCollection:ArrayCollection  = new ArrayCollection([{firstName: 'Murat', lastName: 'Yener'}, {firstName: 'Yunus', lastName: 'Bayraktar'}]);

                  private function showName():void{

                        Alert.show(myGrid.selectedItem.firstName+" "+myGrid.selectedItem.lastName);

                  }

            ]]-->

       

 

 

This example binds the arrayCollection with the dataGrid and adds several event listeners, the itemFocusOut event shows how the data is syncronised.

 

Flex offers to communicate with the server in several ways such as, http request, webservices and remoting. We will cover the last two in this article. We already enabled web services on the client side so all we need to do is type the wsdl adress in our flex application.

        id="wService" wsdl="http://localhost:8080/WorkshopJava/BankOperations?wsdl" >

              name="findCustomer" result="Alert.show('Customer Found'); showCustomerDetails();" fault="Alert.show('error')">

             

       

...

      private function showPartyList(res:ResultEvent):void{

            if (res.result!=null){

                                   Alert.show( res.result.name );

            }

      }

 

Our request to send is an event and the asyncronous response which will be received is also an event. To capture that response we register an event listener. Flex uses Dynamic Objects which are not strongly casted, you can even add a new field to the received object. Dynamic objects very easy and fast to implement but since they must be used carefully.

 

Remoting is a faster and more efficient way to communicate with the server. Until last January remoting was an expensive option under the name of Live Services. Adobe open sourced a subset of live services under the name of BlazeDS which is completely free. Just as Java remoting the Flex client can call any of the server side methods in a native way and transfer seriliazed objects. To enable Blaze remoting, several xml config files added to the server side. This config files can be found under flex directory under resources. You may freely copy these files into your application and change them according to your sunction and service names. To enable our server to load up our blaze configuration, following line must be added to web.xml.

 

      <listener>

            <listener-class>flex.messaging.HttpFlexSessionlistener-class>

      listener>

      <servlet>

            <servlet-name>MessageBrokerServletservlet-name>

            <servlet-class>flex.messaging.MessageBrokerServletservlet-class>

            <init-param>

                  <param-name>services.configuration.fileparam-name>

                  <param-value>/WEB-INF/flex/services-config.xmlparam-value>

            init-param>

 

            <init-param>

                  <param-name>flex.write.pathparam-name>

                  <param-value>/WEB-INF/flexparam-value>

            init-param>

            <load-on-startup>1load-on-startup>

      servlet>

 

Now our Spring bean  is also available for remoting. To start using remoting we must have an equivalent of the entities of the server side on the client side. To show an example below there is the ActionScript remote class equivalent of our Branch entity.

 

package org.flexjava.workshop.entity

{

      import mx.collections.ArrayCollection;

     

      [RemoteClass(alias="org.flexjava.workshop.entity.Customer")]

      public class Customer

      {

            public var id:Number;

            public var name:String;

            public var customerNumber:String;

            public var address:String;

            public var tckNumber:String;

            public var vkNumber:String;

            public var accounts:ArrayCollection;

 

      }

}

 

To use remoting on the previous web service call example;

        id="rObj" result="showCustomerDetails(event)" destination="bankDestination" endpoint="http://localhost:8080/WorkshopJava/messagebroker/amf"/>

 

To call call remote findCustomer method we can just use “rObj.findCustomer” any response will trigger showCustomerDetails method, and the response will have a concrete Customer object. These are the basic communication examples.However, in the code example given with the CD or downloaded from CVS, you will find more advanced 2 actionscript classes which are coded to organise method calls. These classes are responsable to register the reponse listeners and to initialise your server address for making your life easier.

BankWebService AS class will load the apprciate wsdl and register your call with the given listener each time you call for a webservice.

      public class BankWebService extends WebService

      {

            public function BankWebService() {

                  this.useProxy = false;

                  this.loadWSDL("http://localhost:8080/WorkshopJava/BankOperations?wsdl");

            }

           

            private function setOperationListener(operation:AbstractOperation, listener:Function):void {

                  if(!operation.hasEventListener(ResultEvent.RESULT)) {

                        operation.addEventListener(ResultEvent.RESULT, listener);

                  }

            }

            public function findCustomer(listener:Function, customerNumber:String):void {

                  var operation:AbstractOperation = getOperation("findCustomer");

                  setOperationListener(operation, listener);

                  operation.send(customerNumber);

            }

 

This service can be used as simple as like this;

 

private function findCustomer():void {

                        Alert.show(txtCustomerNumber.text);

                        bankService.findCustomer(findCustomerListener, txtCustomerNumber.text);

                  }

In this method we get the value of  txtCustomerNumber.text and call the methos with that parameter. The response will trigger findCustomerListener function.

 

To use the same example with remoting, we use the remoting equivalents of this class which is named, BankService.

      public class BankService extends RemoteObject

      {

            public function BankService() {

                  super("BankDestination");

                  endpoint = "http://localhost:8080/WorkshopJava/messagebroker/amf";

            }

           

            private function setOperationListener(operation:AbstractOperation, listener:Function):void {

                  if(!operation.hasEventListener(ResultEvent.RESULT)) {

                        operation.addEventListener(ResultEvent.RESULT, listener);

                  }

            }

           

            public function findCustomer(listener:Function, customerNumber:String):void {

                  var operation:AbstractOperation = getOperation("findCustomer");

                  setOperationListener(operation, listener);

                  operation.send(customerNumber);

            }

 

This service can be used in a similar way;

                  private function findCustomer():void {

                        Alert.show(txtCustomerNumber.text);

                        bankService.findCustomer(findCustomerListener, txtCustomerNumber.text);

                  }

 

The response listener will receive a customer object.

private function findCustomerListener(event:ResultEvent):void {

                        if (event.result == null) {

                             Alert.show("Customer not exist with the given number!");

                             return;

                        }

                        customer = Customer(event.result);

                        if (this.currentState == "CUSTOMER_DETAIL"

                             || this.currentState == "DRAW_MONEY"

                             || this.currentState == "INVEST_MONEY"

                             || this.currentState == "TRANSFER_MONEY") {

                             this.currentState = "CUSTOMER_DETAIL";

                             bindData();

                        } else {

                             this.currentState = "CUSTOMER_DETAIL";

                        }

                  }

 

In this example, which is the same as the code given with the cd, we change our current state and bind our new received data if needed.

 

 

Eclipse is a great platform for development with its unlimited plugins and extentions.Although this example uses so little of its capabilities we tried to show how easy your development process can be with the approciate tools and with some addition from Flex, your client software will be richer and more trendy.

 

 

 

Murat Yener
Murat Yener
Yunus Bayraktar
Yunus Bayraktar

What do you think?

JAX Magazine - 2014 - 06 Exclucively for iPad users JAX Magazine on Android

Comments

Latest opinions