How to remove your site from Google Safe Search black list

You may have tried to search on Google while Safe Search option is turned on for your domain and couldn’t find any results from your website. In that case, most likely, Google is considering your site as an adult website. It appears that Google is checking history of your domain as well and if your domain was once blocked by Safe Search option, no matter if you have changed your content, your domain will keep being black listed by Safe Search and resulting loss traffic and money for your business. Google Safe Search black list removal task in this tutorial tends to provide a suggestion to help you resolve this issue on your domain.

One of our domains ( GChat.com ) got hit with this forumla which once were blacklisted by this option, more than 10 years ago, even though a long time is past, the domain is still black listed and not even any contents from subdomains can be listed while Safe Search option is turned on.

After a bit of research, we have noticed that search engines such as Yahoo and Goole may be using 3rd party data to evaluate websites to identify which category they are. If the domain you are using is black listed by Safe Search, you can try to submit a reconsideration request on one of these sites which Trend Site Safety tool:

http://global.sitesafety.trendmicro.com/

Using this link, you can get status of your domain to identify which category it is listed under and then click on the reclassify request and submit it for a future review, There is a chance that this might save you some traffic on your search result.

After that, submit a review request to Google using the following link:

http://support.google.com/webmasters/bin/request.py?contact_type=safe_search

Another tip I would give you is to avoid placing too many links on your other Safe sites to your black listed site, otherwise there is a good chance that your other site get black listed by Google as well.

You may try to send a reconsideration request on Google Webmaster tools as well, however in this case most likely you will hear from them that there is no manual action require to be taken on your domain.

Posted in SEO | Comments Off

How to erase hard drive securely

Erase Hard DriveWhen it gets to the time to return your server to your provider, you need to securely remove your files from your server before returning your server, specially if you have sensitive data in there and you do not want the next person who gets the server to be able to access your data using data recovery tools.

Some software packages provide tools to zero write the entire disk after removing your files to make it impossible to recover your data, however if you are looking for a simple option, you can write your own shell script to do it for you by copying a dummy file over and over on a folder in your server until your disk gets full.

This tutorial explains how to erase hard drive securely on a Linux machine, if you are using a Windows, you can create a batch file using similar commands.

1. Backup all of your data, there is no way back so ensure that you have backed up all of your files.

2. Next step is to remove your data including your database files and any sort of sensitive information you may have. You may format your hard disk if you have access to it and then start the following task after formatting your disk, otherwise you can remove all of your files, databases, configuration files, SSH private and public keys ( /root/.ssh folder).

3. Create a dummy file so we can copy it over and over to fill the entire disk, to create a dummy file, you can use the following bash script:

cd /
nano copy.sh

And copy the following in the file:

for i in {0..10000000}
do
 echo '0000000000' >> dummy
done

for a in {1..1000000}
do
 cp dummy $a
done

Hit Ctrl+o , Press Enter key and then press Ctrl+x to exit.

Run the following command to generate the dummy file:

sh copy.sh &

Now you can logout and the server should copy the dummy file to fill the disk. Depending the disk size and processor speed, the time it takes to complete this process may vary. On an Intel quad core processor it took me about 2 hours to finish the task on a 1TB hard disk.

Posted in Information Technology | 2 Comments

What is a memory leak

What is a memory leak

In computers, a memory leak refers to software programs which consume memory but fail to release it. This will usually cause memory overflow, slowing down the entire system and sometimes crashing the software. Memory leaks are a common issue when writing programs in Java language. Java garbage collector will destroy the ghost objects which do not have any references in the memory, however if you leave a reference open to objects, the garbage collector will fail to remove that object and the memory will be kept in use.

How to detect memory leak in Java

Fortunately, there are some tools coming with Java which helps us easily identify a memory leak in our software and resolve it. These tools includes JMAP and JHAT. First step would be to identify how much memory your Java application is consuming normally and then watch the memory use for any suspicious behaviour. In Linux you can run “top” command to monitor memory usage for your applications:

java-memory-usage

In this example, the software is using 471MB memory which I would suspect something is going wrong as this amount keep growing by time. The next step would be to export the heap from memory into a binary file for analysis. This way we can detect which section in our file is causing this memory leak. To do so, we will need jmap command and the process id which we can get it from the “top” command ( in this example 4779 ).

jmap -heap:format=b 4779

After running this command, we have the heap.bin file which then can be used with jhat (Java Heap Analysis Tool) command, You can increase the maximum memory usage depending the heap size to avoid memory overflow error:

jhat -J-Xmx1000m heap.bin

After running this command, you will now have access to the JHAT web interface analysis using the default port number 7000 by accessing the following URL:

http://127.0.0.1:7000/

In this section, you will have a summary of all classes and instances in the memory, Scroll down and click on the Heap Histogram link, then click on the Instance count to find out which objects have most of the instances in the memory:

java-heap-histogram

In this example, the top instances are object, string and integer variables, however one of the items in the list refers to com.mysql.jdbc.JDBC4PreparedStatement class which means that we have left the PreparedStatement object instances open after executing the query. This usually happens if you do not close the ResultSet and PreparedStatement objects in your function.

Solution

The safest way to run queries is to use a finally block in the try/catch statements to close the objects in there in case of any errors which may occur during execution of your query:

public void getOrders( int CustomerId ) throws SQLException {

    PreparedStatement query = null;
    ResultSet rs = null;

    String queryString =
        "select * from orders where customer_id = ?";

    try
    {
        query = con.prepareStatement(queryString);
        query.setInteger ( 1 , customerId );
        rs = query.executeQuery();
    }
    catch (SQLException e )
    {
        System.out.println ( "Error: " + e.getMessage() );
    }
    finally
    {
        if (rs != null)
        {
            rs.close();
        }
        if (query != null)
        {
            query.close();
        }
    }
}
Posted in Tutorials | Comments Off

Android REST Communication

Android REST Communication

Introduction

Mobile devices are getting popular and many people are carrying a mobile device with Internet connectivity in their pockets. Designing a scalable solution to allow these devices to communicate to a central server to perform operation is a becoming necessary for businesses and organizations.
The Android-JBridge project is an open source mobile to server implantation which allows Android mobile devices to connect to the web services on the central server.

This project is deployed on Google Code and can be accessed at: Android JBridge

The source code for both mobile client and server are accessible in there as well as the compiled EAR file to be deployed under the JBoss application server.
This project demonstrates on how to connect to the REST web services from the Android client to insert, update, select or delete resources in the web server. This project uses JBoss 4.x for the application server with RESTEasy 2 framework from the JBoss community with Android SDK which runs on the Android OS 2.2 and higher.

Retrieving data via REST

To retrieve data from the REST web services, Products activity sends a request to the doGet method in the RestEasy class by passing the products web services URI and this function opens a httpGet request to the products method in the RESTEasy to get the JSON formatted data by adding accept “application/json” header to the request:

public static JSONObject doGet(String url) {
    JSONObject json = null;
    HttpClient httpclient = new DefaultHttpClient();
    // Prepare a request object
    HttpGet httpget = new HttpGet(url);
    // Accept JSON
    httpget.addHeader("accept", "application/json");
    // Execute the request
    HttpResponse response;
    try {
        response = httpclient.execute(httpget);
        // Get the response entity
        HttpEntity entity = response.getEntity();
        // If response entity is not null
        if (entity != null) {
            // get entity contents and convert it to string
            InputStream instream = entity.getContent();
            String result= convertStreamToString(instream);
            // construct a JSON object with result
            json=new JSONObject(result);
            // Closing the input stream will trigger connection release
            instream.close();
        }
    } catch (ClientProtocolException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (JSONException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    // Return the json
    return json;
}

Inserting data via REST

To insert a new record in the JBoss database or adding a new resource, doPost method is used in the RESTEasy class. It is possible to use doPut as well, however to demonstrating Post method, in this implantation we have used doPost for insert and doPut for update purpose:

public static HttpResponse doPost(String url, JSONObject c) throws ClientProtocolException, IOException 
    {
        HttpClient httpclient = new DefaultHttpClient();
        HttpPost request = new HttpPost(url);
        StringEntity s = new StringEntity(c.toString());

        s.setContentEncoding("UTF-8");
        s.setContentType("application/json");

        request.setEntity(s);
        request.addHeader("accept", "application/json");

        return httpclient.execute(request);
}

Updating data via REST

To update an existing record, doPut option is being used which in this example, we will reduce the product quantity after user clicks on the buy button:

public static HttpResponse doPut(String url, JSONObject c) throws ClientProtocolException, IOException
{
        HttpClient httpclient = new DefaultHttpClient();
        HttpPut request = new HttpPut(url);
        StringEntity s = new StringEntity(c.toString());
        s.setContentEncoding("UTF-8");
        s.setContentType("application/json");

        request.setEntity(s);
        request.addHeader("accept", "application/json");

        return httpclient.execute(request);
}

Delete records via REST

To delete a product from the database, doDelete method in the RestEasy class is being used. Similar to the doPut method, this method connects to the RESTEasy web services providing the id number in the URL , for example to delete a product with product id of 1 we can pass: http://127.0.0.1/JBridge/product/1/delete. Following method defines doDelete method in the Android RestEasy class:

public static void doDelete(String url) throws  ClientProtocolException, IOException{
    	HttpClient httpclient = new DefaultHttpClient();
    	HttpDelete delete = new HttpDelete(url);
    	delete.addHeader("accept", "application/json");
    	httpclient.execute(delete);
}

JBoss Application Server

The server application consist of entity beans, session beans, servlets, web pages and REST web services. Entity beans are our entity classes such as Product which will be mapped to the database tables as well. Session beans are the core components to perform operations to store and retrieve the data from database and act as a bridge between our REST web services and the database. The servlet provides operations between web pages and our session beans. So it handles requests and responses made from web pages in the JBoss. REST web services are implemented to accept requests from our mobile client and connect to the session beans to pass the queries and return the results from session beans.

Android REST
The server application which includes a servlet and web page GUI which allows developers to perform testing, however the key components of this project lies under Android client and RestEasy web services. The servlet and web layout will be accessible via following URL:

http://127.0.0.1:8080/JBridge/Shop

JBoss application server will run on the server and depending on the project scale can be clustered to run on multiple servers to provide better performance.

One of the features of RESTEasy is supporting JSON (JavaScript Object Notation) which is a lightweight standard designed data interchange. Data transfer between mobile client and server will be in form of JSON which is a new concept in this prototype and can be evaluated by comparing to the other data types. In the RESTEasy web services in this project both JSON and XML annotations uses for the data retrieval purposes which enables the system to support both data types. By default the web service returns XML data type unless it is defined in the header to return JSON data. The reason is that XML data type is more human readable than JSON and it helps for testing and development purposes by visiting the REST resources URIs to view XML data. In our Android client, we use Accept JSON header to make sure that we get JSON data type from the web services.

Posted in Mobile Programming, Tutorials | Comments Off

Delphi Tutorial

Delphi Tutorial

In the following Delphi tutorial, I will provide you with documentation and sample code on how to build a simple delphi program called Cash Register.

Introduction

Cash register is an application which enables the operator to add products, add transactions and calculate the total price, VAT and total gross cost. Also operator can calculate the amount he needs to return to customer by entering the customer tendered price. Objective of this software is to enable the operator to add products and calculate transactions, total price, VAT and total gross price. Another feature is to edit the existing transaction if the quantity is entered wrong by the operator. Add and Edit product forms can be accessed through Edit menu. After adding products it’s possible to save the products in a file and open it later through File menu.

Delphi Tutorial sample application

Program Documentation

Data Structure

Data for the products is maintained with an array products of TProduct record as follows:

TProduct = record
name: string[20];
price: real;

Program operation

Initialisation

When program starts, in the formCreate procedure in the main form, number of the products will be set to zero (listing line 593).

Adding a product

When operator opens the edit menu and click on add, mnuEditAddProductClick procedure opens the add product form (listing line 298). When operator clicks on the add button in the add product form, btnAddClick procedure executes by validating the data and if the data is correct and its not already exists, this procedure adds the product in the main form combo box as well as to the products array and clears the product name and price after addition. (Listing line 634)

Editing existing products

By selecting Modify… under Edit menu, Edit Product form appears in the modal mode by calling frmEditProduct.ShowModal; procedure (Listing line 305), in the Edit product form, operator selects a product from products combo box which executes cmbProductsChange procedure (Listing line 753) which shows the selected product name and price in the product and price text boxes. When operator clicks on the save, btnSaveClick will be executed (Listing line 766) by validating the values, if the values are correct it updates products array in the main form (Listing line 799) as well as combo box in the edit product and main product. Then it clears the price and product text box and also deselects the combo box by setting its itemindex to zero (Listing line 809).

Adding transactions

When operator clicks on the add button in the main form, btnAddClick procedure in the main form executes and validates the values, if the values are valid, it calculates the net cost, vat and then total cost and adds them to the products, quantities, prices, net cost, vat, and gross cost list boxes. (Listing line 186) and then clears the text boxes, deselect the list boxes by setting their itemIndex to -1 and then calls calculateAll procedure (Listing line 254). TfrmMain.calculateAll procedure is the main calculation procedure (Listing line 333), in this procedure, all the items in the transaction will be calculated for the total net cost, total vat and total gross cost. If there is any value entered in the customer tendered price, the change value will be calculated in this module as well.

Saving products in a file

When operator selects Save As… in the file menu, mnuFileSaveClick procedure in the main menu executes (Listing line 135) which opens dlgSave dialogue box for the operator to select a file for save, if the file already exists, operator will get a confirmation message which the file will be overwritten to confirm it (Listing line 147), If operator clicks on the No button, procedure will be aborted by calling the Exit procedure. Otherwise cash register will open the selected file and write all items in the products array to the file and then closes the file.

Opening products file

When operator selects Open… in the file menu, mnuFileOpenClick executes (Listing line 258), when user selects a file, a confirmation message will appear for the operator which the changes will be lost, if operator clicks on the no button, open procedure will be aborted by calling Exit procedure, other wise number of products will be set to zero (Listing line 274) and cash register loads all of the records (Listing line 281) from the selected file into the products array as well as products combo box in the main form .

Exiting cash register

When operator clicks on the Exit in the File menu, mnuExitClick executes (Listing line 129) by calling close procedure (Listing line 131).

Getting About Form

When operator selects About… in the main form, mnuHelpAboutClick procedure executes which opens About form in the modal mode (Listing line 309) by calling frmAbout.ShowModal; procedure.

Program Listing

Main Form

unit Main;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Menus, StdCtrls;

type
  TProduct = record
    name: string[20];
    price: real;
  end;
  TfrmMain = class(TForm)

  private
    { Private declarations }
  public
    { Public declarations }
    products: array of TProduct;
    nProducts: integer;
  end;

var
  frmMain: TfrmMain;

implementation

uses editProduct, RegisterProduct, About;

{$R *.dfm}

// invokes when user clicks on the exit menu in the file menu and closes the application
procedure TfrmMain.mnuExitClick(Sender: TObject);
begin
  close;
end;

// This procedure invokes when user clicks on the save in the file menu
procedure TfrmMain.mnuFileSaveClick(Sender: TObject);
var
  productsFile: file of TProduct;
  i: integer;
begin

{ 
When user selects a file if file is exists, show a confirmation message to the user if user clicks on the No button; exit the procedure 
}
  if dlgSave.Execute then
  begin
    if fileExists(dlgSave.FileName) then
    begin
       if MessageDlg('Do you want to overwrite the file?',
                                mtConfirmation, [mbYes, mbNo], 0) = mrNo then
       begin
         Exit;
       end
    end;

    // Open the file, if file is not exists, then create it, if already exists, file will be overwritten
    AssignFile(productsFile,dlgSave.FileName);
    reWrite(productsFile);

    // Loop through registered items and write them in the products file
    for i:= 0 to nProducts-1 do
    begin
      write(productsFile,products[i]);
    end;

    closeFile(productsFile);
  end;
end;

{
  This procedure invokes when user selects a product in the products combo box,
  The selected item price will appear in the price textbpx
}
procedure TfrmMain.cmbProductsChange(Sender: TObject);
var
  strPrice: string;
begin

  // convert the selected item price to string, display in the price text box, clear quantity
  Str(products[cmbProducts.ItemIndex].price:0:2,strPrice);
  edtPrice.Text := strPrice;
  edtQuantity.Clear;
end;

//  This procedure invokes when user clicks on the add button
procedure TfrmMain.btnAddClick(Sender: TObject);
var
  rlPrice, rlNetCost, rlVat, rlGrossCost: real;
  intQuantity,intError: integer;
  strNetCost, strVat, strGrossCost: string;
begin

  // If no item is selected exit procedure and set focus on products combo box
  if cmbProducts.ItemIndex = -1 then
  begin
    showMessage('Please select a product');
    cmbProducts.SetFocus;
    Exit;
  end;

  // Validating price
  Val(edtPrice.Text,rlPrice,intError);
  if intError <> 0 then
  begin
    showMessage('Price is not valid');
    edtPrice.SetFocus;
    Exit;
  end;

  // Validating quantity
  Val(edtQuantity.Text,intQuantity,intError);
  if intError <> 0 then
  begin
    showMessage('Quantity is not valid');
    edtQuantity.SetFocus;
    Exit;
  end;

  // calculating the amounts
  rlNetCost := rlPrice*intQuantity;
  rlVat := rlNetCost*17.5/100;
  rlGrossCost := rlNetCost + rlVat;

  // Converting Netcost, VAT and Gross Cost variables to string
  Str((rlNetCost):0:2,strNetCost);
  Str((rlVat):0:2,strVat);
  Str((rlGrossCost):0:2,strGrossCost);

  // Adding product item in the list boxes, quantity, price, netcost, vat and gross cost
  lstProducts.Items.Add(cmbProducts.Text);
  lstQuantities.Items.Add(edtQuantity.Text);
  lstPrices.Items.Add(edtPrice.Text);
  lstNetCost.Items.Add(strNetCost);
  lstVat.Items.Add(strVat);
  lstGrossCost.Items.Add(strGrossCost);

  // Disable Update button
  btnUpdate.Enabled := false;

  // Deselect the list boxes
  lstProducts.ItemIndex := -1;
  lstQuantities.ItemIndex := -1;
  lstPrices.ItemIndex := -1;
  lstNetCost.ItemIndex := -1;
  lstVat.ItemIndex := -1;
  lstGrossCost.ItemIndex := -1;

  // Clearing the form
  cmbProducts.ItemIndex := -1;
  edtPrice.Clear;
  edtQuantity.Clear;

  // Call the calculateAll procedure to calculate all values once again
  calculateAll;
end;

// This procedure invokes when user clicks on the open menu in the file
procedure TfrmMain.mnuFileOpenClick(Sender: TObject);
var
  productsFile: file of TProduct;
begin
   if dlgOpen.Execute then
  begin

  // Show confirmation message to the user before loading the file, exit if user clicks on the No.
  if MessageDlg('All of the changes will be lost, do you want to continue?',
                           mtConfirmation, [mbYes, mbNo], 0) = mrNo then
  begin
    Exit;
  end;

    // Clear products combo box, set products to 0
    cmbProducts.Clear;
    nProducts := 0;

    // Open the products file
    AssignFile(productsFile,dlgOpen.FileName);
    reset(productsFile);

    // Loop through records in the file and load them in the combo boxes and products array
    while not EOF(productsFile) do
    begin
      setLength(products,nProducts+1);
      read(productsFile,products[nProducts]);
      cmbProducts.Items.Add(products[nProducts].name);
      nProducts := nProducts+1;
    end;

    // Close the file
    closeFile(productsFile);
  end;
end;

// Executes when user clicks on the register menu under products; shows add product form
procedure TfrmMain.mnuEditAddProductClick(Sender: TObject);
begin
  frmAddProduct.ShowModal;
end;

// Executes when user clicks on the Modify menu under products; displays edit product form
procedure TfrmMain.mnuEditModifyClick(Sender: TObject);
begin
  frmEditProduct.ShowModal;
end;

// This procedure invokes when user clicks on the about submenu in the help menu
procedure TfrmMain.mnuHelpAboutClick(Sender: TObject);
begin
  frmAbout.ShowModal;
end;

// Selects all list boxes along when user clicks on an item in the products list box
procedure TfrmMain.lstProductsMouseDown(Sender: TObject;
                     Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  with lstProducts do
  begin
    lstQuantities.ItemIndex := ItemIndex;
    lstPrices.ItemIndex := ItemIndex;
    lstNetCost.ItemIndex := ItemIndex;
    lstVat.ItemIndex := ItemIndex;
    lstGrossCost.ItemIndex := ItemIndex;
  end;
end;

{
  Form main calculate procedure to calculate all list boxes as well as customer tendered price
  if user entered any, this procedure shows total netcost, vat and total gross cost as well

}
procedure TfrmMain.calculateAll;
var
  rlTotalNetCost, rlTotalVat, rlTotalGross: real;
  rlNetCost, rlVat,rlGross, rlTenderedPrice, rlChange: real;
  i, error: integer;
  strTotalNetCost, strTotalVat, strTotalGross, strChange: string;
begin

  // Reset all of the totals to 0
  rlTotalNetCost :=0;
  rlTotalVat := 0;
  rlTotalGross := 0;

  // loop through items in one of the list boxes and calculate total amounts
  for i:=0 to lstNetCost.Count-1 do
  begin
    Val(lstNetCost.Items[i],rlNetCost,error);
    Val(lstVat.Items[i],rlVat,error);
    Val(lstGrossCost.Items[i],rlGross,error);
    rlTotalNetCost := rlTotalNetCost + rlNetCost;
    rlTotalVat := rlTotalVat + rlVat;
    rlTotalGross := rlTotalGross + rlGross;
  end;

  // Display the total amounts in the total labels
  Str(rlTotalNetCost:0:2,strTotalNetCost);
  Str(rlTotalVat:0:2,strTotalVat);
  Str(rlTotalGross:0:2,strTotalGross);
  lblTotalNetCost.Caption := '£ '+strTotalNetCost;
  lblTotalVat.Caption := '£ '+strTotalVat;
  lblTotalGross.Caption := '£ '+strTotalGross;

  // reset background color
  lblChange.Color := ClBtnFace;

  // If tendered price text box is not empty then calculate the change as well
  if edtTenderedPrice.Text <> '' then
  begin

    // Validate the tendered price
    Val(edtTenderedPrice.Text,rlTenderedPrice,error);
    if error = 0 then
    begin

      // Calculate the change, if tendered price is valid, if its not enough display the message
      rlChange := rlTenderedPrice - rlTotalGross;
      Str(rlChange:0:2,strChange);
      lblChange.Caption := '£ '+strChange;
      if rlChange < 0 then
      begin
        lblChange.Color := ClRed;
        lblChange.Caption := 'Amount is not enough';
      end;
    end

    // if customer tendered price is not valid then display appropriate caption
    else
    begin
      lblChange.Color := ClRed;
      lblChange.Caption := 'Amount is not valid';
    end;
  end

  // If user does not enter any amount in the tendered price, set the change to 0
  else
  begin
    lblChange.Caption := '£ 0.00';
  end;
end;

// This procedure invokes when user changes customer tendered price textbox
procedure TfrmMain.edtTenderedPriceChange(Sender: TObject);
begin
  // Calling calculateAll procedure to recalculate all form for updating change label as well
  CalculateAll;
end;

// This procedure invokes when user clicks on the delete selected in the edit menu
procedure TfrmMain.mnuEditDeleteSelectedClick(Sender: TObject);
var
  intSelectedItem: integer;
begin

  // Check if no item is selected, display a message
  intSelectedItem := lstProducts.ItemIndex;
  if intSelectedItem = -1 then
  begin
    showMessage('No transaction is selected to delete.');
  end

  // If an item is selected then delete from the list boxes and calculate all totals
  else
  begin
    lstProducts.DeleteSelected;
    lstQuantities.DeleteSelected;
    lstPrices.DeleteSelected;
    lstNetCost.DeleteSelected;
    lstVat.DeleteSelected;
    lstGrossCost.DeleteSelected;
    CalculateAll;
  end;
end;

// This procedure invokes when user clicks on the delete last item in the edit menu
procedure TfrmMain.mnuEditDeleteLastClick(Sender: TObject);
var
  intLastItem: integer;
begin
  // Display an error message when there is no item to delete
  intLastItem := lstProducts.Count-1;
  if lstProducts.Count = 0 then
  begin
    showMessage('There is no item to delete.');
  end

  // Delete last item from list boxes and recalculate all totals
  else
  begin
    // delete last item from list boxes
    lstProducts.Items.Delete(intLastItem);
    lstQuantities.Items.Delete(intLastItem);
    lstPrices.Items.Delete(intLastItem);
    lstNetCost.Items.Delete(intLastItem);
    lstVat.Items.Delete(intLastItem);
    lstGrossCost.Items.Delete(intLastItem);
    CalculateAll;
  end;
end;

// This procedure invokes when user clicks on the new sub menu in the file menu
procedure TfrmMain.edtFileNewClick(Sender: TObject);
begin

  // display a confirm message for clearing the form for new customer
  if MessageDlg('Are you sure?', mtConfirmation, mbOkCancel, 0) = mrOk then
  begin

    // Clear the add transaction form and all list boxes, recalculate totals to set them all to 0
    cmbProducts.ItemIndex := -1;
    edtPrice.Clear;
    edtQuantity.Clear;
    lstProducts.Clear;
    lstQuantities.Clear;
    lstPrices.Clear;
    lstNetCost.Clear;
    lstVat.Clear;
    lstGrossCost.Clear;
    calculateAll;
  end;
end;

{
  This procedure invokes when user clicks on the products list box
  And selected transaction appears in the add transaction form for editing
}
procedure TfrmMain.lstProductsClick(Sender: TObject);
var
  i: integer;
begin

  // loop through products to find the selected item to display it in the products combo box
  for i:=0 to nProducts-1 do
  begin
    if cmbProducts.Items[i] = lstProducts.Items[lstProducts.ItemIndex] then
    begin
      cmbProducts.ItemIndex := i;
    end;
  end;

  // update price and quantity to the selected transaction, then enable the update button
  edtPrice.Text := lstPrices.Items[lstProducts.itemIndex];
  edtQuantity.Text := lstQuantities.Items[lstProducts.itemIndex];
  btnUpdate.Enabled := true;
end;

{
  This procedure invokes when user clicks on the update button, to save the changes of the selected transaction.
  It will update transaction price and quantity and calculate all transactions again
}
procedure TfrmMain.btnUpdateClick(Sender: TObject);
var
  intQuantity, error: integer;
  rlPrice, rlNetCost,rlVat,rlGrossCost: real;
  strNetCost, strVat, strGrossCost: string;
begin

  // Abort if no transaction is selected
  if lstProducts.ItemIndex = -1 then
  begin
    showMessage('No transaction is selected');
    Exit;
  end;

  // Validating the price, display error message and then exit if price is not valid
  Val(edtPrice.Text,rlPrice,error);
  if error <> 0 then
  begin
    showMessage('Price is not valid');
    edtPrice.SetFocus;
    Exit;
  end;

  // Validating the quantity, display error message, exit the procedure if quantity is not valid
  Val(edtQuantity.Text,intQuantity,error);
  if error <> 0 then
  begin
    showMessage('Quantity is not valid');
    edtQuantity.SetFocus;
    Exit;
  end;

  // Calculating the amounts
  rlNetCost := rlPrice * intQuantity;
  rlVat := rlNetCost * 17.5/100;
  rlGrossCost := rlNetCost + rlVat;
  str(rlNetCost:0:2,strNetCost);
  str(rlVat:0:2,strVat);
  str(rlGrossCost:0:2,strGrossCost);

  // Update the transaction list boxes with new values
  lstQuantities.Items[lstProducts.ItemIndex] := edtQuantity.Text;
  lstPrices.Items[lstProducts.ItemIndex] := edtPrice.Text;
  lstNetCost.Items[lstProducts.ItemIndex] := strNetCost;
  lstVat.Items[lstProducts.ItemIndex] := strVat;
  lstGrossCost.Items[lstProducts.ItemIndex] := strGrossCost;

  // Deselect the list boxes as well as disable the update button
  lstProducts.ItemIndex := -1;
  lstQuantities.ItemIndex := -1;
  lstPrices.ItemIndex := -1;
  lstNetCost.ItemIndex := -1;
  lstVat.ItemIndex := -1;
  lstGrossCost.ItemIndex := -1;
  btnUpdate.Enabled := false;

  // call calculate procedure to re calculate the form
  calculateAll;

  // Clear quantity text box and display a message after updating the transaction
  edtQuantity.Clear;
  showMessage('Item updated successfully');
end;

// Display a confirmation message before closing the application for saving data
procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  if MessageDlg('If you exit, the changes after last save will be lost, do you want to
                           continue?',mtConfirmation, [mbYes, mbNo], 0) = mrNo then
  begin
    Exit;
  end;
end;

// This procedure invokes when form is being created to set the number of products to 0
procedure TfrmMain.FormCreate(Sender: TObject);
begin
  nProducts := 0;
end;

end.

end.

Register Product Form

unit RegisterProduct;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TfrmAddProduct = class(TForm)
    GroupBox1: TGroupBox;
    Label1: TLabel;
    Label2: TLabel;
    edtProduct: TEdit;
    edtPrice: TEdit;
    btnAdd: TButton;
    procedure btnAddClick(Sender: TObject);
    procedure FormShow(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  frmAddProduct: TfrmAddProduct;
implementation
uses
  Main;
{$R *.dfm}

// This procedure adds a product when users click on the add button
procedure TfrmAddProduct.btnAddClick(Sender: TObject);
var
  rlPrice: real;
  i, errorPrice: integer;
begin

  // Validate the product title, display error message and exit if product title is blank
  if edtProduct.Text = '' then
  begin
    showMessage('Product name is required');
    edtProduct.SetFocus;
    Exit;
  end;

  // Validate product price, display an error message and exit if price is not valid
  Val(edtPrice.Text,rlPrice,errorPrice);
  if errorPrice <> 0 then
  begin
    showMessage('Price is not valid');
    edtPrice.SetFocus;
    exit;
  end;

  // Check if this product name is not already registered
  for i:=0 to frmMain.nProducts-1 do
  begin
    {
     If find product name in the registered products case insensitive (using lowerCase function)
     To make sure user cannot register an item twice even by passing uppercase words
    }
    if lowerCase(frmMain.products[i].name) = lowerCase(edtProduct.Text) then
    begin
      showMessage('This item already has been registered');
      edtProduct.SetFocus;
      Exit;
    end;
  end;

  //  Registering the product in the main form by adding it to the products array
  with frmMain do
  begin
    setLength(products,nProducts+1);
    products[nProducts].name := edtProduct.Text;
    products[nProducts].price := rlPrice;
    cmbProducts.Items.Add(edtProduct.Text);
    nProducts := nProducts+1;
  end;

  // Clearing product name and product price and display a message
  edtProduct.Clear;
  edtPrice.Clear;
  showMessage('Product registered successfully');
end;

// This procedure invokes when add product form is being displayed
procedure TfrmAddProduct.FormShow(Sender: TObject);
begin
  edtProduct.SetFocus
end;
end.
Edit Product Form

unit editProduct;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TfrmEditProduct = class(TForm)
 
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  frmEditProduct: TfrmEditProduct;

implementation
uses
  Main;
{$R *.dfm}

{
  This procedure invokes when users selects Modify Product in the edit menu on the 
  main form, so it loads the registered products in the products combo box
}
procedure TfrmEditProduct.FormShow(Sender: TObject);
var
  i: integer;
begin
  cmbProducts.Clear;
  edtPrice.Clear;

  // Loop through registered products and add them to the products combo box
  for i:=0 to frmMain.nProducts-1 do
  begin
    cmbProducts.Items.Add(frmMain.products[i].name);
  end;
end;

{
  This procedure invokes when users select a product in the products combo box in the 
  modify product form, and it displays product price in the price edit box
}
procedure TfrmEditProduct.cmbProductsChange(Sender: TObject);
var
  strPrice: string;
begin
  edtProductName.Text := cmbProducts.Text;
  str(frmMain.products[cmbProducts.ItemIndex].price:0:2,strPrice);
  edtPrice.Text := strPrice;
end;

{
  This procedure invokes when user clicks on the save button And it verify price and if the price is valid, it saves the changes in the products array in the form1
}
procedure TfrmEditProduct.btnSaveClick(Sender: TObject);
var
  intError, intItem: integer;
  rlPrice: real;
begin

  // Exit if no item is selected
  intItem := cmbProducts.ItemIndex;
  if intItem = -1 then
  begin
    showMessage('Please select a product');
    exit;
  end;

  // Validating product name
  if edtProductName.Text = '' then
  begin
    showMessage('Product name is required');
    edtProductName.SetFocus;
    exit;
  end;

  // Validating price
  Val(edtPrice.Text,rlPrice,intError);
  if intError <> 0 then
  begin
    showMessage('Price is not valid');
    edtPrice.SetFocus;
    Exit;
  end;

  // Changing the price to the new price and title
  cmbProducts.Items[intItem] := edtProductName.Text;
  frmMain.products[intItem].price := rlPrice;
  frmMain.products[intItem].name := edtProductName.Text;
  frmMain.cmbProducts.Items[intItem] := edtProductName.Text;

  showMessage('Product saved successfully');
  // Deselecting the item in the combo box

  // Clearing the title and price textbox as well as deselect items in the products combo box
  edtProductName.Clear;
  edtPrice.Clear;
  cmbProducts.ItemIndex := -1;

  // Deselect product in main form and clear price and quantity
  frmMain.cmbProducts.ItemIndex := -1;
  frmMain.edtPrice.Clear;
  frmMain.edtQuantity.Clear;
end;

// Delete selected product from cash register
procedure TfrmEditProduct.btnDeleteClick(Sender: TObject);
var
  i: integer;
begin

  //If there is no item selected, display error message
  if cmbProducts.ItemIndex = -1 then
  begin
    showMessage('Please select a product');
    exit;
  end;

  // Loop in products array in the form1 to delete the selected product from array and form
  for i:= cmbProducts.ItemIndex to frmMain.nProducts-2 do
  begin
    frmMain.products[i] := frmMain.products[i+1];
  end;

  // Delete selected product as well as reducing one from number of the products
  frmMain.nProducts := frmMain.nProducts -1;
  cmbProducts.DeleteSelected;

  // Clearing text boxes as well as display a message box
  edtPrice.Clear;
  edtProductName.Clear;
  showMessage('Selected product has been removed succeffully');
end;
end.
About Form

unit About;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TfrmAbout = class(TForm)
    btnOk: TButton;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    procedure btnOkClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  frmAbout: TfrmAbout;

implementation
uses
  Main;
{$R *.dfm}

// This procedure executes when user clicks on the Ok button to close the about form
procedure TfrmAbout.btnOkClick(Sender: TObject);
begin
  close;
end;
end.

Download link: Delphi-Tutorial.zip

Posted in Tutorials | Comments Off

How to change your domain name keeping your SEO ranking

Change the domain name

You may get into a point where you need to change the domain name of your website to a new one due a rebranding. You must ensure you have no other choice as this change is a major in terms of SEO and will have impact on your search engine rankings and losing traffic at least for a while is inevitable. To minimize the impact, you need to consider a few steps before redirecting your current website to the new domain name. The picture below represents the sudden traffic loss after changing the domain name:

Change domain name

Parked domain names

Probably your new domain name will be a parked domain and not in use, so you need to be careful with that. Never rush to dive into migrating your domain name, instead take your time and build up a few simple web pages, relevant to your existing one and upload it into your web server and point your new domain name in there. Wait for few weeks so when you type your domain name, it appears first item in the Google search results. If you have access to the pages linking to your current domain, you can change the links to the new domain in this period.

Redirecting web pages

At this step, start by redirecting your existing pages to the new domain. Matt Cuffs, the head of Google’s Webspam team suggests that moving pages individually rather than redirecting whole domain at once. This can be done easily by adding a 301 redirects in your .htaccess file, For example the following line will redirect a single page to your new domain:

redirect 301 /product.html http://www.newdomain.com/product.html

Or if you prefer to redirect each folder, you can use the following code which redirects whole product folder:

redirect 301 /product/ http://www.newdomain.com/product/

I suggest you to use canonical tag in your pages as well. This tells Google that where is the actual location of each page:

<link rel="canonical" href="http://www.gchat.com/" />

Check Google webmaster tools

Now keep an eye on Google webmaster tools, and be patient, It takes a couple of weeks for Google Bot to migrate your links from your old domain to the new domain. You will also notice that number of Indexes will start to reduce on your old domain and instead they will be increased in your new domain name. To make the process faster, you can use the Change website feature in the webmaster tools by selecting your new domain name from the list.

Posted in SEO | Comments Off

SoftLayer Firewall Review

SoftLayer Firewall Review

I have decided to give a try to different DDoS protection providers to find out which one provides the best deal, so I start by the SoftLayer Firewall Review.

I have started this experiment by SoftLayer Firewall protection ( 1Gbps ) on a quad core dedicated server. The server were setup within 4 hours and delivered quickly, the support was fair, so lets get to the firewall test result.

My target site usually used to get attacks ranging from 60 Mbps and up to 600 Mbps ( Rarely during the past year). After just a couple of days of using this server, I have received an altert indicating that my server were null routed for 24 hours with the following details which are network level statistics and not server level:

Details of the event follow:
Exceeded Bits In: 4 G (Threshold: 750 M)
Exceeded Packets In: 468.3 k (Threshold: 250 k)

After calling them, I was told by one of the SoftLayer staff:

“I understand you have a 1gbps firewall protection however firewalls do not protect against network level DDoS attacks. There are other companies provide DDoS protection and you need to look into them.”

And finally here is the server traffic report which shows the server level DDoS attacks which are just below 70Mbps:

Bottom line:

Don’t get the SoftLayer Firewall protection, it doesn’t protect you against DDoS attacks.

Posted in Reviews | Comments Off

Java chat bot – Free open source chat robot

Introduction

MajBot is a Java-Based chat bot which responses based on the messages that it receives. It uses an external data file (XML file) to make it easier for users to extend its features and its domain. MajBot uses dynamic features to retrieve weather information from Yahoo Weather API. It allows multiple messages per state to make it possible to display random message for similar questions to make the bot more interactive.
Each state can expect multiple keywords or no keywords which returns user to the default state. It also supports regular expressions for better user input processing. MajBot can learn new keywords by asking questions from user and provide their answer for them in the future questions.

Chat Bot

License: GPL, download link is available at the bottom of this article.

At a glance

It is easy to customize the MajBot by configuring data.xml file, this file contains different states and keywords inside each state, once a keyword is matched, user will be transferred to the target state, MajBot stats from State “0” by default, here is a simple configuration file:

<?xml version="1.0" encoding="UTF-8"?>
<Config>
    <State id="0">
        <message>Hello, How are you?</message>
        <keywords>                    <keyword target="1">happy</keyword>
        </keywords>
    </State>

    <State id="1">
      <message>wow, you are happy!</message>
      <message>glad to hear that!</message>
   </State>
   <InvalidMessages>
        <message>Huh, I didn't understand?</message>
        <message>What do you mean?</message>
    </InvalidMessages>
</Config>

In the above example, If user enters happy keyword, bot moves to State “1″ and display one of  state “1″ messages randomly, If user enters any other strings, one of the invalid messages will appear.

Keyword tag contains multiple attributes to make it possible to customize the bot according to the requirements.

Navigation

To navigate user between different states, keyword tag is being used with target attribute, the matching keyword will transfer user to its target, it is possible to use multiple keywords and multiple messages for each state, in this case everytime a random message appears. It is easy to use multiple keywords by separating the keywords by comma, if any of these keywords matches, user will be transferred to the target state:

<State id="16">
<message>Hello, how are you today?</message>
<message>How are you feeling?</message>
<message>How are you doing?</message>
<keyword target="11">happy, very happy</keyword>
<keyword target="13">not happy,not good,not fine,sad,upset</keyword>
<keyword target="23">fine, good, thanks</keyword>
<keyword target="14">yourself</keyword>
</State>

 

Using the weather feature

To use weather feature, keyword tag should contain two attributes, className and arg, className should set to Weather and arg should set to “today”, “tomorrow” or “dayaftertomorrow” keywords. Here is an example to get today’s weather:

<keyword className="Weather" arg="today">weather</keyword>

Result:

You: how is the weather
Bot: I think today is Fog

Catch all

To transfer user to a custom state when user enters an unexpected keyword, “*” symbol can be used:

<State id="11">
<message>That's great, why you are happy?</message>
<keywords>
<keyword target="21">lottery</keyword>
<keyword target="22">*</keyword>
</keywords>
</State>

Regular Expressions

Using Regular Expression makes it possible to process user’s input and extract data from their inputs; MajBot stores these data into a dictionary and it is possible to use these dynamic data in different states, following example demonstrates how to ask a user’s name and response with a greeting message with user’s name in the greeting:

<?xml version="1.0" encoding="UTF-8"?>
<Config>
<State id="0">
<message>Hello, My name is MajBot, what is your name?</message>
<keywords>
<keyword target="2" variable="name">([a-zA-Z ]+)</keyword>
</keywords>
</State>
<State id="16">
<message>Hello [name], nice to see you!</message>
</State>
</Config>

Result:

Bot: Hello, My name is MajBot, what is your name?
You: Majid 
Bot: Hello majid, nice to see you!

In the above example “([a-zA-Z )+)" regex accepts any characters betwen a to z  (case insensitive) including spaces and store the matching word to name variable, then by using [name] in the message, user’s name will be replaced with this tag. (For more information about Regex syntax refer to Java Regex Documentation).

Adding priorities to keywords

By default the longest matching keyword will be the best match, however sometimes we need to give extra points to some of keywords so in case both of the keywords matches, the keywords with higher points selected for the best match, in this case we can use points attribute:

<Config>
<State id="0">
<message>Hello, My name is MajBot, what is your name?</message>
<keywords>
<keyword target="16" variable="name" points="2">.*my name is ([a-zA-z]+).*</keyword>
<keyword target="16" variable="name">([a-zA-Z ]+)</keyword>
</keywords>
</State>
<State id="16">
<message>Hello [name], nice to see you!</message>
</State>
</Config>

Result:

Bot: Hello, My name is MajBot, what is your name?
You: my name is Majid
Bot: Hello majid, nice to see you!

In the above example we are adding 2 points for the first keyword so if user enters “my name is Majid”, it only gets the name instead of returning “My name is Majid” as name.

Learning new words

It is possible to ask the user about unknown keywords and add dynamic keywords and states for the new keyword, if in the future user enters same keyword, his answer will be replied back to the user. For this purpose we can use variable tag to get user’s keyword first and then asking a question about that subject and storing the subject result by using learn attribute:

 <State id="1">
<message>What do you want to talk about?</message>
<keyword variable="subject" target="27">([a-zA-z]+)</keyword>
</State>
<State id="27">
<message>What is [subject]?</message>
<keyword target="43" variable="result" learn="subject">(.*)</keyword>
</State>

Result:

Bot: What do you want to talk about?
You: football 
Bot: What is football?
You: it is a good game 
Bot: I see...
Bot: What do you want to talk about?
You: football 
Bot: it is a good game

As it is shown in the above example, bot learns about football keyword and then send the response back to the user when user sends same keyword again.

How to run MajBot

MajBot includes 7 classes and one data.xml file. It also uses Apache HttpdClient libraries to connect to Yahoo Weather API. All of the classes are compiled into MajBot.jar file and you can run the jar file using provided run.sh file which contains:

java -cp MajBot.jar bot.Main

To run MajBot you can simply type:

sh run.sh

If you are using windows, you can run run.bat file instead.

After starting the bot, user can enter a message and start chating with MajBot.

Download link: Download MajBot source from GitHub.com

Posted in Scripts, Tutorials | 1 Comment

What is Servlet

What is servlet? A servlet is a Java class which can be accessed by via request-response methods.

This application is designed to demonstrate a distributed system development which uses servlets and  EJBs. The project consists of two servlets including Registration which handles login and register processes and Shop servlet which handles all the functionalities related to the shop applications such as product list and shopping basket.

License: MIT License, download link is available at the end of this article.

There are several JSP pages which provide UI and graphics and forms to allow users communicate with servlets. Requests will be sent to the servlets and servlets connect to the EJB components to perform the task. EJBS connect to the data store (hypersonic in this example) to store, update or fetch the data and return it to the servlets. These data will be sent to the JSP pages again and displayed to the user, the graph below represents how this project communicate with different components:

Distributed-Systems

It is an easy task to change the data source from hypersonic to any database servers such as MySQL or Oracle if required.

Definitions and reasoning

Entity Beans

The case study use case diagram defines 2 entities for this project which includes Customer and Product, so two EJB entity beans has been developed. According to the case study, since a login facility is required, Customer entity bean should at least contain id, username and a password property plus a validatePIN method.

Product entity bean contains id, name and price. However since we need a method to find out if we have enough items in the stock, we need to add quantity property to this entity bean as well. This method gets a number and checks with quantity property and returns a boolean value which indicates if there are enough stock available for this item or not. Similarly, purchase method is implemented to reduce quantity by number of provided items to reduce it from the stock. Both of these entity beans will be mapped to tables (customer and product) to update the table in the data source defined in the persistence unit.

Following annotations has been used in these entity beans and reasons are explained:

  • @Id: Used to define the id field as identifier for these entity beans. This field acts as a primary key.
  • @Table: Defines table name for each entity bean to be used by persistence units.
  • @Column(name = “xxx”): defines column name for each attribute in the database, xxx to be replaced by the database field name for each attribute.
  • @GeneratedValue(strategy = GenerationType.AUTO): used with @Id annotation to make the id column auto number, so in the database each new record contains a unique id number which will be incremented.
  • @Override: This annotation is used in some methods which declared in their super classes to tell the compiler to override the element.

Session Beans

There are 2 stateless session beans in this project and no statefull session beans. For shopping basket we will use servlet session object which will be handled by the application server. Here are our session beans:

RegistrationBean which consist of two methods, one for register data and one for validate customer login. It is defined as stateless and here are annotations for this bean:

  • @Stateless(name = “registration”): Defines this session bean as stateless and map it to the registration name. This name will be used to lookup this session bean via initial context.
  • @Remote(RegistrationBean.class): Defines  remote interface of this class and also allows remote lookup to access this session bean.
  • @Local: Allows local lookup to be performed to access this beans.
  • @PersistenceContext: causes the entity manager to obtain an instance.

ShopBean which contains 5 methods to handle shop related functionalities. These methods provide a list of features including: get list of all the products, find a product by  id, add a new product, buy product and checkout. It is also stateless because we do not need to keep any state of products in this session bean and shopping basket will be handled by servlet sessions. Here are the annotations used in this session bean:

  • @Stateless(name = “shop”): Defines this session bean as stateless and map it to the sho name. This name will be used to lookup this session bean via initial context.
  • @Remote(ShopBean.class): Defines  remote interface of this class and also allows remote lookup to access this session bean.
  • @Local: Allows local lookup to be performed to access this beans.
  • @PersistenceContext: causes the entity manager to obtain an instance.

Servlets

There are 2 servlets in this project which communicate with session beans and return the result to the JSP pages.

  • Registration Servlet
    First servlet is Registration which handles register and login features of the project, This servlet has been mapped in the web.xml file defined in the WEB-INF folder to /Registration URL. This servlet uses HttpSession class to access users session data to store login details of the user so we know if user is already logged in or not.
  • Shop Servlet
    Shop servlet handles all other shop functionalities such as loading list of the products, adding product in the basket and checkout. This servlet also mapped to /Shop URL defined in the web.xml file. Shop servlet also uses HttpSession class to access users session to store shopping basket object and also check if the user is already logged in and get user’s details as well.

JSP Pages

There are 4 main jsp pages in this project including: index.jsp, products.jsp, item.jsp and basket.jsp. Also footer.jsp contains footer notes and header.jsp which contains menu and header graphics are included in all of these 4 pages. Using include tag. Here is an overall structure of the JSP pages:

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Page title</title>
</head>
<body>
<div id=”wrapper”>
<%@include file="header.jsp" %>
Contents take place here
<%@include file="footer.jsp" %>
</div>
</html>
  • Index.jsp
    This page is the default page and contains registration and login form. Action attribute of both forms are set to “/TVUShop/Registration” which will cause the data to be posted to the Registration servlet.
  • Products.jsp
    This page provides list of all the products in the stock and allows user to select a product. In order to access this page, customer must register first and then login. After login user will be redirected to the “/TVUShop/Shop” servlet which explained earlier. This servlet gets list of the products from Shop session bean and sets the result in the products attribute:
// Get products collection
Collection<Product> products = shop.getProducts(keyword);
 // store the product in the products attribute
request.setAttribute("products", products); 
// load products.jsp page with products attribute
RequestDispatcher requestDispatcher = getServletContext().getRequestDispatcher ("/products.jsp");
requestDispatcher.forward(request, response);

Using requestDispatcher, request will be forwarded to the products.jsp page so list of the products will be accessible in that page:

// Get collection of all the products in the database
Collection<Product> products = (Collection) request.getAttribute("products");

// Default error message
String msg = "";

// If no product is retreived, display a message
if(products.isEmpty()){
msg = "Your search did not match any items.";
}

Using a for loop products will be written on the web page:

// loop through all the products
for(Product product: products){

// print product details on the webpage
out.println("<a href='Shop?action=displayItem&id=" + product.getId() + "'>
<img   src='products/" + product.getPicture() + "' alt='" + product.getName() + "'height='120' /></a>");
…
}
  • Item.jsp
    When user selects a product, this page appears which contains product details and a form to let user add the product to the shopping cart by entering quantity. This page will be accessible through “TVUShop/Shop” servlet, however this time action variable from the products page will send “displayItem” value with an “id” number to indicate the product id:

    http://127.0.0.1:8080/TVUShop/Shop?action=displayItem&id=2

    Shop servlet detects this request using following condition:

    // display a product by given id
    if (action.equals("displayItem")) {
    // get product by id
      Product item = shop.findProduct(id);
    // store item in the attributes and open item.jsp page
    request.setAttribute("item", item);
                        RequestDispatcher requestDispatcher = getServletContext().getRequestDispatcher("/item.jsp");
                      requestDispatcher.forward(request, response);
    }
  • Using ShopBeanImpl session bean, Shop servlet fetches the product from database by id and adds it to the request attributes and then forward it to the item.jsp page. This page can now get product details and display it on the screen:
    // Get selected product
    Product item = (Product) request.getAttribute("item");
  • Basket.jsp
    This page will provide shopping basket items for the user and allow them to choose to empty the basket or checkout. This page will be accessible via “/TVUShop/Shop” servlet. When action querystring is set to “basket” this servler will get shopping basket from user session data and forward the request to the basket.jsp page:

     http://127.0.0.1:8080/TVUShop/Shop?action=basket
    if (action.equals("basket")) {
    // If emtpy cart button is clicked, remove basket session
    
    if (request.getParameter("btnEmpty") != null) {
      session.removeAttribute("basket");
    }
        // open basket.jsp page
        RequestDispatcher requestDispatcher =     getServletContext().getRequestDispatcher("/basket.jsp");
    requestDispatcher.forward(request, response);
    }

Basket page then gets basket attribute using following code:

// Get shopping basket from users session
ArrayList<Product> basket = (ArrayList<Product>) session.getAttribute("basket");

// If basket is null, set it to an empty arraylist
if ( basket == null){
  basket = new ArrayList<Product>();
}

Configuration files

Configuration files structure

  • application.xml
    Java EE Deployment Descriptor which identifies the application description, modules and web URIs. This file is located inside the META-INF folder of the ear file:
<application>
  <display-name>TVUShop EJB</display-name>
  <module>
    <web>
        <web-uri>tvushop.war</web-uri>
        <context-root>/TVUShop</context-root>
    </web>
  </module>
  <module>
    <ejb>tvushop.jar</ejb>
  </module>
</application>
  • persistence.xml
    Defines persistent unit to be accessed by the entity manager. The java:/DefaultDS  points to the HSQL DB which is embedded inside the JBoss. This file located in the META-INF folder of the .jar file. This jar file contains entity bean and session beans:
<?xml version="1.0" encoding="UTF-8"?>
<persistence>
  <persistence-unit name="TVUShopEJB">
    <jta-data-source>java:/DefaultDS</jta-data-source>
    <properties>
        <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
    </properties>
  </persistence-unit>
</persistence>
  • jboss-web.xml
    Defines the context-root in the EAR file for the web applications. Also another way to define this context root is in the application.xml file.This file is located inside the war/WEB-INF folder:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
<context-root>/TVUShop</context-root>
</jboss-web>
  • web.xml
    This file defines the servlets and servlets mappings in the web application .war files. This file is located inside .war/WEB-INF folder:
<web-app>
  <description>TVUShop EJB</description>
  <!-- ### Servlets -->
  <servlet>
    <servlet-name>Registration</servlet-name>
    <servlet-class>server.servlet.Registration</servlet-class>
  </servlet>  
  <servlet>
    <servlet-name>Shop</servlet-name>
    <servlet-class>server.servlet.Shop</servlet-class>
  </servlet>
  <!-- The servlet and jsp page mappings -->
  <servlet-mapping>
    <servlet-name>Registration</servlet-name>
    <url-pattern>/Registration</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>Shop</servlet-name>
    <url-pattern>/Shop</url-pattern>
  </servlet-mapping>
</web-app>
  • Build.xml
    This file is not a part of the EAR files, however it is used for building and compiling the project by Apache ant. This file compiles all the classes and make .jar, .war and .ear archives.

Deployment and testing

To deploy the project, you should copy tvushop.ear in the jboss/server/default/deploy folder, following screen shot demonstrate tvushop.ear successful deployment on the jboss:

JBoss Application Server

Testing

Now you can access the default TVUShop page at the following URL:

http://127.0.0.1:8080/TVUShop/

ServletDownload Link: Download TVUShop.zip

Posted in Scripts, Tutorials | Comments Off

What is ERP

What is ERP?

Enterprise resource planning (ERP) system is defined as an integrated computer-based system which manages both internal and external resources such as financial resources and human resources. This article explains what is ERP and also discusses about its benefits, limitations and technical issues.

SAP is the worlds’ leading provide of e-business software solutions which helps to improve relationships with customer and partner, streamlining operations and achieving significant effectiveness through their supply chain. The SAP ERP application supports all required functions and features for business processes and operations efficiency depending specific needs of the industry.

“We chose SAP in the mid-nineties as the leading integrated software for covering all business across the whole of Shell. Upstream, downstream marketing in chemicals and of course as time went on we needed more and more significant programs for implementing SAP.”  said David Lee, chief architect for the SAP global initiative at Shell.

Shell Exploration and Production Co, (Shell EP) teamed up with Accenture to develop one singe IT platform based on SAP R/3. This would make it possible for all users around the world to access the new system which leads to increasing performance and more profit for the company. The reason that Shell chosen Accenture was for their leading expertise on both on-shore consultants and off-shore development work.

Also Shell has teamed up with LogicCMG secures IT services and the first project worth up to 20 million Euros was for the implementation of a SAP solution to help standardise the operational processes within Shell Europe Oil products.

“Standardisation and simplification of our processes and systems in a cost effective manner is more important than ever. We have therefore initiated a programme to achieve these objectives in Europe. LogicaCMG has given us consultancy and programme services in the past and we are convinced that they will be an excellent business partner to us for the future and therefore will help us to achieve our ambitions.” said: Jos Steeman, responsible for business process standardisation

Benefits

Implementation of ERP was the company’s need to integrate it’s information system. The major benefit of this implementation is allowing employees to have quick and easy access to a wide range of key enterprise systems including emails, databases, searches and notification systems globally. According to Sap shell press release, approximately 85,000 Shell employees around the world got access to use all these features by logging into one system and via a single interface. For security reasons by using roles which is defined in the ERP system, employees get limited access to the features depending on their access levels.

The new solution enables Shell EP to increase operational performance and efficiency by sharing best practices, greater transparency, compatibility of information process across organizations and standardization of business processes. Using the new flexible foundation enabled the company in achieving its current priorities such as resource base growth, operational excellence, competitive cost structure, stronger ability to enable new technologies, processes and business initiatives as they merge to help the organization lead its industry.

“We see an employee portal as an enabler to improve our employee value proposition, as well as improving employee effectiveness in the business context,” said Alan Matula, Oil Products CIO of Shell.

Using one ERP package will cause fewer data errors and improving decision making processes for Shell management which all lead to reduce spending cost of the company significantly and successful conversion of new business opportunities.

The Shell blue-print program delivered first value in consolidating the infrastructure to provide one system which support team and provide common practices globally.

“Real big benefits intended to be from the standardization of the processes globally that effort is still continuing and will go on for a number of years.” said Alan Lomax, head of process improvement–work management and integration.

Now Shell is producing an integration of Primavera with SAP to integrate the planning; So the SAP is act as a work management system and also a procurement system as well as finance system all in a single solution.

Problems and technical issues

Local processes and a multitude of bespoke systems and stand alone instances of SAP, complexity and cost of which threatened to impair the efficiently of the company operations. Existing Shell EP systems required implementation of standard processes to increase performance and also consolidation and harmonizing was necessary.

To implement the SAP, company required experience related in different areas such as: data centre infrastructure, Network infrastructure, server configuration, disk subsystem design, installation, and configuration, infrastructure security, high availability and disaster recovery, database backup, operations and SAP technology.

References

  • Wikipedia, Enterprise resource planing [Online], available: http://en.wikipedia.org/wiki/Enterprise_resource_planning [15 Dec 2010]
  • Accenture, Shell Exploration and Production Co.: SAP Solutions [Online], available: http://accenture.com/Global/Technology/Enterprise_Solutions/SAP_Solutions/Client_Successes/Shell.htm [28 Dec 2010]
  • Accenture, Teaming with Shell to drive business value [Online], available: http://www.accenture.com/NR/rdonlyres/CAFC5179-0728-4046-BD97-6EB781A9D875/0/Accenture_Teaming_with_Shell_to_Drive_Business_Value.pdf
  • LogicaCMG, LogicaCMG secures IT services partner status with Shell [Online], available:
    http://www.logica.com/we-are-logica/media-centre/news/2003/logicacmg-secures-it-services-partner-status-with-shell/ [1 Jan 2010]
Posted in Information Technology | Comments Off