Platinum Partner
java,netbeans,bigdata,frameworks,spring,tool,mvc,extjs,json-p

Mixing ExtJs, JSON-P and Java Web on NetBeans

In a previous article  I demonstrated how to build a ExtJs application. In the next lines I will show the content of a small patient management application using ExtJs as client-side framework and Java web with Spring framework in server-side.

I- Database schema table

Below the DDL script of the Patient table: 

CREATE TABLE Patient(
Id INT NOT NULL AUTO_INCREMENT,
FirstName VARCHAR(100) NOT NULL,
LastName  VARCHAR(100) NOT NULL, 
Address   VARCHAR(100) NOT NULL,
City      VARCHAR(100) NOT NULL,
Country   VARCHAR(100) NOT NULL,
PRIMARY KEY (ID)
);

II - Client-side : ExtJs  + MVC architecture

We need first to create a new Java Web project ( please, follow this tutorial ) with Spring Web MVC into NetBeans IDE.  Mine was named PatientManagement .

In the second time we create the client side using ExtJs framework and respecting MVC architecture ( Controller and View). Below the picture summarizing the project : 

The index.html file code source  :

<!--
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<!DOCTYPE html>
<html>
    <head>
        <title>PATIENT MANAGEMENT</title>
        <link rel="stylesheet" type="text/css" href="ext/resources/css/ext-all.css">
        <script type="text/javascript" src="ext/ext-all.js"></script>
        <script type="text/javascript" src="app.js"></script>
    </head>
    <body></body>
</html>
The app.js  file content :
Ext.Loader.setConfig({
    enabled: true
});

Ext.application({
    name: 'PM',
    appFolder: 'front/app',
    controllers: ['PatientController'],
    autoCreateViewport: true,
    launch: function() {

    }
});

Views :

The AppToolbar.js file content :

/* 
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

Ext.define('PM.view.patient.AppToolbar', {
    extend: 'Ext.panel.Panel',
    alias: 'widget.apptoolbar',    
    initComponent: function() {
        this.dockedItems = [
            {xtype: 'toolbar',
                dock: 'top',
                items: [
                    {
                        xtype: 'cycle',
                        showText: 'true',
                        text: '<html><b>Patient</b></html>',
                        width: '300',
                        menu: {
                            xtype: 'menu',
                            width: '150',
                            items: [
                                {
                                    xtype: 'menucheckitem',
                                    text: 'New patient',
                                    action: 'create'
                                },
                                {
                                    xtype: 'menucheckitem',
                                    text: 'Patients list',
                                    action: 'listing'
                                }

                            ]
                        }
                    }
                ]
            }

        ];

        this.callParent(arguments);
    }
});

The AddPatient.js file code source :

/* 
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */


Ext.define('PM.view.patient.AddPatient', {
    extend: 'Ext.window.Window',
    alias: 'widget.addpatient',
    title: 'Create a patient',
    layout: 'fit',
    autoShow: true,
    initComponent: function() {
        this.items = [
            {
                xtype: 'form',
                bodyStyle: {
                    background: 'none',
                    padding: '10px',
                    border: '0'
                },
                items: [
                    {
                        xtype: 'textfield',
                        name: 'firstname',
                        allowBlank: false,
                        fieldLabel: '<html><b>Firts Name</b></html>'
                    },
                    {
                        xtype: 'textfield',
                        name: 'lastname',
                        allowBlank: false,
                        fieldLabel: '<html><b>Last Name</b></html>'
                    },
                    {
                        xtype: 'textfield',
                        name: 'address',
                        fieldLabel: '<html><b>Address</b></html>',
                        allowBlank: false
                    },
                    {
                        xtype: 'textfield',
                        name: 'city',
                        fieldLabel: '<html><b>City</b></html>',
                        allowBlank: false
                    },
                    {
                        xtype: 'textfield',
                        name: 'country',
                        fieldLabel: '<html><b>Country</b></html>',
                        allowBlank: false

                    }
                ]
            }
        ];
        this.buttons = [
            {
                text: 'Save',
                action: 'save'
            },
            {
                text: 'Cancel',
                scope: this,
                handler: this.close
            }
        ];

        this.callParent(arguments);
    }
});
The viewport  Viewport.js file content :
Ext.define('PM.view.Viewport', {
    extend: 'Ext.container.Viewport',
    alias: 'widget.viewport',    
    items: [
        {
            xtype: 'apptoolbar'
        }],
    initComponent: function() {
       this.callParent(arguments);
    }
}); 

Controller :

The content of PatientController.js is below :

/* 
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */


Ext.define('PM.controller.PatientController', {
    extend: 'Ext.app.Controller',
    views: ['patient.AddPatient', 'patient.AppToolbar'],
    init: function() {
        this.control({
            'addpatient button[action=save]': {
                click: this.doCreatePatient
            },
            'apptoolbar > toolbar > cycle > menu > menucheckitem[action=create]': {
                click: this.onCreatePatient
            }

        });
    },
    onCreatePatient: function() {
        //The panel to create a patient appears on the screen
        var view = Ext.widget('addpatient');
    },
    //Function to create a new patient
    doCreatePatient: function(button) {
        var win = button.up('window'),
                form = win.down('form'),
                values = form.getValues()
        if (form.getForm().isValid()) {
            Ext.Ajax.request({
                url: 'PatientController',
                method: 'POST',
                params: {
                    patientcreateData: Ext.encode(values)
                },
                scope: this,
                stateful: true
            });

            win.close();
        }
    },
});

In this controller we use the singleton Ext.Ajax  to send an HTTP request to a remote server. In our example we will use the method POST to send the data and we will use the server-side servlet  PatientController.java (see below the code source).  The JSON object is patientcreateData.

The web.xml file has been modified according the project to have index.html file as welcome page.

<welcome-file-list>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>

III - Server-side implementation

Below the sample of Java files defining the server-side of the application :

The model  Patient.java  code is here:

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.model.patientmanagement;

/**
 *
 * @author constantin
 */
public class Patient {

    private int id;
    private String firstname;
    private String lastname;
    private String address;
    private String city;
    private String country;

    public Patient() {
    }

    public Patient(String firstname, String lastname, String address, String city, String country) {
        this.firstname = firstname;
        this.lastname = lastname;
        this.address = address;
        this.city = city;
        this.country = country;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getFirstname() {
        return firstname;
    }

    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }

    public String getLastname() {
        return lastname;
    }

    public void setLastname(String lastname) {
        this.lastname = lastname;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

}

The DAO PatientDao.java file content is here :

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.dao.patientmanagement;

import com.model.patientmanagement.Patient;
import java.util.List;
import javax.sql.DataSource;

/**
 *
 * @author constantin
 */
public interface PatientDao {

    public void setDataSource(DataSource dataSource);

    public void createPatient(String firstname, String lastname, String address, String city, String country);

    public Patient getPatientById(Integer id);

    public void deletePatient(Integer id);

    public List<Patient> listPatients();

    public void updateFirstName(Integer id, String firstname);

}

The PatientTemplate.java source :

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.impl.patientmanagement;

import com.dao.patientmanagement.PatientDao;
import com.model.patientmanagement.Patient;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;

/**
 *
 * @author constantin
 */
public class PatientTemplate implements PatientDao {

    private DataSource dataSource;
    private JdbcTemplate jdbcTemplateObject;

    @Override
    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
        this.jdbcTemplateObject = new JdbcTemplate(dataSource);
    }

    @Override
    public void createPatient(String firstname, String lastname, String address, String city, String country) {
        try {
            String Sql = "insert into Patient(firstname, lastname, address, city,country) values (?,?,?,?,?)";
            jdbcTemplateObject.update(Sql, firstname, lastname, address, city, country);

        } catch (DataAccessException ex) {
            System.out.println("Error" + ex.getMessage());
        }
    }

    @Override
    public Patient getPatientById(Integer id) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public void deletePatient(Integer id) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public List<Patient> listPatients() {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public void updateFirstName(Integer id, String firstname) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

}

The PatientMapper.java file content is:

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.impl.patientmanagement;

import com.model.patientmanagement.Patient;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.RowMapper;

/**
 *
 * @author constantin
 */
public class PatientMapper implements RowMapper<Patient> {

    @Override
    public Patient mapRow(ResultSet rs, int i) throws SQLException {
        //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
        Patient patient = new Patient(); 
        patient.setId(rs.getInt("id"));
        patient.setFirstname(rs.getString("firstname"));
        patient.setLastname(rs.getString("lastname"));
        patient.setAddress(rs.getString("address"));
        patient.setCity(rs.getString("city"));
        patient.setCountry(rs.getString("country"));  
        return patient ;  
    }
}

Here the doPost method code source of the servlet PatientController.java :

 @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
      
        //Get the context of the application
        ServletContext servletContext = this.getServletContext();

        WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);

        String patientcreateData = request.getParameter("patientcreateData");

        //I parse here the json object
        GenericJsonParser jsonPatient = new GenericJsonParser();
        HashMap<String, String> patientMap = jsonPatient.getJsonMap(patientcreateData);

        String firstname = patientMap.get("firstname");
        String lastname = patientMap.get("lastname");
        String address = patientMap.get("address");
        String city = patientMap.get("city");
        String country = patientMap.get("country");

        PatientTemplate patient = (PatientTemplate) wac.getBean("patienttemplate");
        
        patient.createPatient(firstname, lastname, address, city, country);               

    }

The class to parse Json object is implemented as shown below  (GenericJsonParser.java):

This class is very important since there is no method in JSON-P API to bind Java object and JSON object. It parses the Json object a return a map that is better easy to be used in Java code.

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.controller.patientmanagement;

import java.io.StringReader;
import java.util.HashMap;
import javax.json.Json;
import javax.json.stream.JsonParser;
import static javax.json.stream.JsonParser.Event.END_OBJECT;
import static javax.json.stream.JsonParser.Event.KEY_NAME;

/**
 *
 * @author constantin Drabo
 * This class allow you to parse a  Json object coming from client side
 */
public class GenericJsonParser {

    public GenericJsonParser() {
    }

    public HashMap<String, String> getJsonMap(String jsonflux) {

        String keyvalue;
        JsonParser parser = Json.createParser(new StringReader(jsonflux));
        JsonParser.Event event = parser.next();

        HashMap<String, String> jsonElements;
        jsonElements = new HashMap<String, String>();

        while (event != END_OBJECT) {
            event = parser.next();
            if (event == KEY_NAME) {
                keyvalue = parser.getString();
                System.out.println("KeyValue === " + keyvalue);
                parser.next();
                jsonElements.put(keyvalue, parser.getString());
            }
        }

        return jsonElements;
    }

}


IV- Run the application

The application will look like this when it is running :

Here a sample data we will save :

When  they click on the button Save they obtain this Json object (here captured by Firebug ) :

{{ tag }}, {{tag}},

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}
{{ parent.authors[0].realName || parent.author}}

{{ parent.authors[0].tagline || parent.tagline }}

{{ parent.views }} ViewsClicks
Tweet

{{parent.nComments}}