Monday, August 22, 2016

RESTful Web Services in Java

Read about REST here...
In the example program REST is implemented using Jersey Framework.
Download Jersey framework from here...
I used Dynamic Web Project in Eclipse for coding. Extract jersey zip file and copy all the .jar files from api, ext, lib folders to WebContent/WEB-INF/lib folder.

Employee.java
 
package in.theinsanetechie.rest;

import java.io.Serializable;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "employee")
public class Employee implements Serializable {

 private static final long serialVersionUID = 1L;
 private int empcode;
 private String name;
 private String designation;
 private float basicpay;
 
 public Employee() {  
 }
 
 public Employee(int empcode, String name, String designation, float basicpay) {
  super();
  this.empcode = empcode;
  this.name = name;
  this.designation = designation;
  this.basicpay = basicpay;
 }

 public int getEmpcode() {
  return empcode;
 }
 
 @XmlElement
 public void setEmpcode(int empcode) {
  this.empcode = empcode;
 }
 
 public String getName() {
  return name;
 }
 
 @XmlElement
 public void setName(String name) {
  this.name = name;
 }
 
 public String getDesignation() {
  return designation;
 }
 
 @XmlElement
 public void setDesignation(String designation) {
  this.designation = designation;
 }
 
 public float getBasicpay() {
  return basicpay;
 }
 
 @XmlElement
 public void setBasicpay(float basicpay) {
  this.basicpay = basicpay;
 }

 @Override
 public boolean equals(Object obj) {
  if (this == obj)
   return true;
  if (obj == null)
   return false;
  if (getClass() != obj.getClass())
   return false;
  Employee other = (Employee) obj;
  if (Float.floatToIntBits(basicpay) != Float
    .floatToIntBits(other.basicpay))
   return false;
  if (designation == null) {
   if (other.designation != null)
    return false;
  } else if (!designation.equals(other.designation))
   return false;
  if (empcode != other.empcode)
   return false;
  if (name == null) {
   if (other.name != null)
    return false;
  } else if (!name.equals(other.name))
   return false;
  return true;
 }

}


EmployeeAccessObject.java
 
package in.theinsanetechie.rest;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;

public class EmployeeAccessObject {

 private String fileName = "Employee.dat";
 
 @SuppressWarnings("unchecked")
 public List getFullList() {
  List list = null;
  File file = new File(fileName);
  try {
   if (file.exists()) {
    FileInputStream fileInputStream = new FileInputStream(file);
    ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
    list = (List) objectInputStream.readObject();
    objectInputStream.close();
   } else{
    Employee employee = new Employee(1001, "The Insane Techie", "Dev", 99999.99f);
    list = new ArrayList();
    list.add(employee);
    saveList(list);
   }
   
  } catch (FileNotFoundException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  } catch (ClassNotFoundException e) {
   e.printStackTrace();
  }
  
  return list;
 }
 
 public Employee get(int empcode) {
  List list = getFullList();
  
  for (Employee temp : list) {
   if (temp.getEmpcode() == empcode) {
    return temp;
   }
  }
  
  return null;
 }
 
 public boolean addToList(Employee emp){
  List list = getFullList();
  boolean exists = false;
  for(Employee temp: list){
   if(temp.getEmpcode() == emp.getEmpcode()){
    exists = true;
    break;
   }
  }  
  if(!exists){
   list.add(emp);
   saveList(list);
   return true;
  }
  return false;
 }
 
 public boolean updateList(Employee emp){
  List list = getFullList();
  for(Employee temp: list){
   if(temp.getEmpcode() == emp.getEmpcode()){
    int index = list.indexOf(temp);   
    list.set(index, emp);
    saveList(list);
    return true;
   }
  }  
  return false;
 }

 public boolean deleteFromList(int empcode){
  List list = getFullList();

  for(Employee temp: list){
   if(temp.getEmpcode() == empcode){
    int index = list.indexOf(temp);   
    list.remove(index);
    saveList(list);
    return true;   
   }
  }  
  return false;
 }
 
 private void saveList(List list) {
  
  File file = new File(fileName);
  try {
   FileOutputStream fileOutputStream = new FileOutputStream(file);
   ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
   objectOutputStream.writeObject(list);
   objectOutputStream.close();
  } catch (FileNotFoundException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  }
  
 }
}


EmployeeService.java
 
package in.theinsanetechie.rest;

import java.io.IOException;
import java.util.List;

import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.OPTIONS;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;

@Path("/EmployeeService")
public class EmployeeService {

 EmployeeAccessObject accessObject = new EmployeeAccessObject();
 private static final String SUCCESS = "success";
 private static final String FAILURE = "failure";


 @GET
 @Path("/employees")
 @Produces(MediaType.APPLICATION_XML)
 public List getFullList(){
  return accessObject.getFullList();
 }

 @GET
 @Path("/employees/{empcode}")
 @Produces(MediaType.APPLICATION_XML)
 public Employee get(@PathParam("empcode") int empcode){
  return accessObject.get(empcode);
 }

 @PUT
 @Path("/employees")
 @Produces(MediaType.APPLICATION_XML)
 @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
 public String add(@FormParam("empcode") int empcode,
   @FormParam("name") String name,
   @FormParam("designation") String designation,
   @FormParam("basicpay") float basicpay,
   @Context HttpServletResponse servletResponse) throws IOException{
  Employee emp = new Employee(empcode, name, designation, basicpay);
  boolean result = accessObject.addToList(emp);
  if(result == true){
   return SUCCESS;
  }
  return FAILURE;
 }

 @POST
 @Path("/employees")
 @Produces(MediaType.APPLICATION_XML)
 @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
 public String update(@FormParam("empcode") int empcode,
   @FormParam("name") String name,
   @FormParam("designation") String designation,
   @FormParam("basicpay") float basicpay,
   @Context HttpServletResponse servletResponse) throws IOException{
  Employee emp = new Employee(empcode, name, designation, basicpay);
  boolean result = accessObject.updateList(emp);
  if(result == true){
   return SUCCESS;
  }
  return FAILURE;
 }

 @DELETE
 @Path("/employees/{empcode}")
 @Produces(MediaType.APPLICATION_XML)
 public String deleteUser(@PathParam("empcode") int empcode){
  boolean result = accessObject.deleteFromList(empcode);
  if(result == true){
   return SUCCESS;
  }
  return FAILURE;
 }

 @OPTIONS
 @Path("/employees")
 @Produces(MediaType.APPLICATION_XML)
 public String getSupportedOperations(){
  return "GET, PUT, POST, DELETE";
 }
}


WebServiceTester.java
 
package in.theinsanetechie.rest;

import java.util.List;

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.MediaType;

public class WebServiceTester  {

 private Client client;
 private String REST_SERVICE_URL = "http://localhost:8080/EmployeeManagement/rest/EmployeeService/employees";
 private static final String SUCCESS="success";
 private static final String PASS = "pass";
 private static final String FAIL = "fail";

 private void init(){
  this.client = ClientBuilder.newClient();
 }

 public static void main(String[] args){
  
  WebServiceTester tester = new WebServiceTester();  
  tester.init();
  tester.testGetFullList();
  tester.testGet();
  tester.testUpdate();
  tester.testAdd();
  tester.testDelete();
 }
 
 private void testGetFullList(){
  GenericType> list = new GenericType>() {};
  List employees = client
    .target(REST_SERVICE_URL)
    .request(MediaType.APPLICATION_XML)
    .get(list);
  String result = PASS;
  if(employees.isEmpty()){
   result = FAIL;
  }
  System.out.println("Test case name: testGetFullList, Result: " + result );
 }

 private void testGet(){
  Employee sampleEmp = new Employee();
  sampleEmp.setEmpcode(1001);

  Employee emp = client
    .target(REST_SERVICE_URL)
    .path("/{empcode}")
    .resolveTemplate("empcode", 1001)
    .request(MediaType.APPLICATION_XML)
    .get(Employee.class);
  String result = FAIL;
  if(sampleEmp != null && sampleEmp.getEmpcode() == emp.getEmpcode()){
   result = PASS;
  }
  System.out.println("Test case name: testGet, Result: " + result );
 }

 private void testUpdate(){
  Form form = new Form();
  form.param("empcode", "1001");
  form.param("name", "Dhanoop Bhaskar");
  form.param("designation", "Computer Scientist");
  form.param("basicpay", "100000.00f");

  String callResult = client
    .target(REST_SERVICE_URL)
    .request(MediaType.APPLICATION_XML)
    .post(Entity.entity(form,
      MediaType.APPLICATION_FORM_URLENCODED_TYPE),
      String.class);
  String result = PASS;
  if(!SUCCESS.equals(callResult)){
   result = FAIL;
  }

  System.out.println("Test case name: testUpdate, Result: " + result );
 }
 
 private void testAdd(){
  Form form = new Form();
  form.param("empcode", "1002");
  form.param("name", "The Insane Techie");
  form.param("designation", "Computer Scientist");
  form.param("basicpay", "100000.00f");

  String callResult = client
    .target(REST_SERVICE_URL)
    .request(MediaType.APPLICATION_XML)
    .put(Entity.entity(form,
      MediaType.APPLICATION_FORM_URLENCODED_TYPE),
      String.class);

  String result = PASS;
  if(!SUCCESS.equals(callResult)){
   result = FAIL;
  }

  System.out.println("Test case name: testAdd, Result: " + result );
 }
 
 private void testDelete(){
  String callResult = client
    .target(REST_SERVICE_URL)
    .path("/{empcode}")
    .resolveTemplate("empcode", 1002)
    .request(MediaType.APPLICATION_XML)
    .delete(String.class);

  String result = PASS;
  if(!SUCCESS.equals(callResult)){
   result = FAIL;
  }

  System.out.println("Test case name: testDelete, Result: " + result );
 }
}


web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
    http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    id="WebApp_ID" version="3.0">
    <display-name>Employee Management</display-name>
    <servlet>
        <servlet-name>Jersey RESTful Application</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
            <init-param>
                <param-name>jersey.config.server.provider.packages</param-name>
                <param-value>in.theinsanetechie.rest</param-value>
            </init-param>
        </servlet>
    <servlet-mapping>
    <servlet-name>Jersey RESTful Application</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>
</web-app>

Tuesday, June 14, 2016

The Insane Techie - Android App



Launched an android app for the blog on 07th June 2016.

Get it from google play store...

Tips for using the app
  • Use in landscape mode while viewing the code snippets.
  • For convenience, I have added major categories as separate feeds in the app (as an update on 08th June 2016).
  • Use Help section for updates about the app.
Thanks :)

Wednesday, March 9, 2016

Installing and Configuring phpMyAdmin in Ubuntu/Linux Mint


Install phpmyadmin
sudo apt-get install phpmyadmin

Configure phpmyadmin
sudo dpkg-reconfigure -plow phpmyadmin

Then select Apache 2 for the webserver you wish to configure.

Try hitting the URL http://localhost/phpmyadmin/

If this does not work, then you have to include the phpMyAdmin-shipped Apache configuration into Apache:

sudo ln -s /etc/phpmyadmin/apache.conf /etc/apache2/conf.d/phpmyadmin.conf
sudo /etc/init.d/apache2 reload

Since Ubuntu 13.10 (Saucy Salamander), Apache no longer loads configuration files from the /etc/apache2/conf.d directory.
Instead, they are placed in the /etc/apache2/conf-available directory which is managed with the a2enconf command.
Therefore, if you need to manually include the phpMyAdmin-shipped Apache configuration file, you must run the following:

sudo ln -s /etc/phpmyadmin/apache.conf /etc/apache2/conf-available/phpmyadmin.conf
sudo a2enconf phpmyadmin
sudo /etc/init.d/apache2 reload

Sunday, February 14, 2016

DNS Lookup - Implementation in C


Read about DNS here...

DNS Lookup - Implementation in C
 
/**dnsclient.c**/
#include"stdio.h"  
#include"stdlib.h"  
#include"sys/types.h"  
#include"sys/socket.h"  
#include"string.h"  
#include"netinet/in.h"  
#include"netdb.h"
#include"arpa/inet.h"
  
#define BUF_SIZE 512
#define SERVER "8.8.8.8"
#define PORT 53
#define WIDTH 16
  
int createSocket();
void createRequest(char * url);
void hexdump (char *desc, void *addr, int len);
void lookUp();

struct query {
	uint16_t length;
	char * url;
	unsigned char request[BUF_SIZE];
	uint16_t reqType;
};

struct query dnsQuery = {
				.length = 12,
				.url = "",
				.reqType = 0x01,
				.request = { 0xDB, 0x42, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
			};

int main(int argc, char** argv) {
	char * url;

	if (argc != 2) {
		fprintf(stderr,"usage: %s hostnameToResolve\n", argv[0]);
		exit(1);
	}

	url = argv[1];
		
	createRequest(url);
	lookUp();
}



int createSocket() {
	int sockfd;

	sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	if (sockfd < 0) {  
		printf("Error creating socket!\n");  
		exit(1);  
	}  
	//printf("Socket created...\n");

	return sockfd;
}

void createRequest(char * url) {
	char * word;
	int i;	
	printf("Asking DNS server %s about %s\n", SERVER, url);
	dnsQuery.url = strdup(url);
	dnsQuery.reqType = 0x01;

	word = strtok(url, ".");
	while (word) {
		printf("parsing hostname: \"%s\" is %d characters\n", word, strlen(word));
		dnsQuery.request[dnsQuery.length++] = strlen(word);
		for (i = 0; i < strlen(word); i++) {
			dnsQuery.request[dnsQuery.length++] = word[i];
		}
		word = strtok(NULL, ".");
	}

	dnsQuery.request[dnsQuery.length++] = 0x00; // End of the host name
	dnsQuery.request[dnsQuery.length++] = 0x00; // 0x0001 - Query is a Type A query (host address)
	dnsQuery.request[dnsQuery.length++] = dnsQuery.reqType;
	dnsQuery.request[dnsQuery.length++] = 0x00; // 0x0001 - Query is class IN (Internet address)
	dnsQuery.request[dnsQuery.length++] = 0x01;
}


// http://stackoverflow.com/questions/7775991/how-to-get-hexdump-of-a-structure-data
void hexdump (char *desc, void *addr, int len) {
    int i;
    unsigned char buff[17];
    unsigned char *pc = addr;

    // Output description if given.
    if (desc != NULL)
        printf ("%s:\n", desc);

    // Process every byte in the data.
    for (i = 0; i < len; i++) {
        // Multiple of 16 means new line (with line offset).

        if ((i % 16) == 0) {
            // Just don't print ASCII for the zeroth line.
            if (i != 0)
                printf ("  %s\n", buff);

            // Output the offset.
            printf ("  %04x ", i);
        }

        // Now the hex code for the specific character.
        printf (" %02x", pc[i]);

        // And store a printable ASCII character for later.
        if ((pc[i] < 0x20) || (pc[i] > 0x7e))
            buff[i % 16] = '.';
        else
            buff[i % 16] = pc[i];
        buff[(i % 16) + 1] = '\0';
    }

    // Pad out last line if not exactly 16 characters.
    while ((i % 16) != 0) {
        printf ("   ");
        i++;
    }

    // And print the final ASCII bit.
    printf ("  %s\n", buff);
}


void lookUp() {
	struct sockaddr_in addr;
	int socket;
	int ret, rcode, size, i;
	int ip = 0, dom = 0;
	int length;
	unsigned char buffer[BUF_SIZE];
	unsigned char tempBuf[3];
	uint16_t QDCOUNT; //No. of items in Question Section
	uint16_t ANCOUNT; //No. of items in Answer Section
	uint16_t NSCOUNT; //No. of items in Authority Section
	uint16_t ARCOUNT; //No. of items in Additional Section
	uint16_t QCLASS; //Specifies the class of the query
	uint16_t ATYPE; //Specifies the meaning of the data in the RDATA field
	uint16_t ACLASS; //Specifies the class of the data in the RDATA field
	uint32_t TTL; //The number of seconds the results can be cached
	uint16_t RDLENGTH; //The length of the RDATA field
	uint16_t MSGID;

	socket = createSocket();

	memset(&addr, 0, sizeof(addr));  
	addr.sin_family = AF_INET;  
	addr.sin_addr.s_addr = inet_addr(SERVER);
	addr.sin_port = htons(PORT);
	size = sizeof(addr);

	hexdump("sending packet", &dnsQuery.request, dnsQuery.length);
	ret = sendto(socket, dnsQuery.request, dnsQuery.length, 0, (struct sockaddr*)&addr, size);
	if (ret < 0) {
		printf("Error Sending Request");
		exit(1);		
	}
	//printf("Sent\n");

	memset(&buffer, 0, BUF_SIZE);
	ret = recvfrom(socket, buffer, BUF_SIZE, 0, (struct sockaddr*)&addr, &size);
	if (ret < 0) {
		printf("Error Receiving Response");
		exit(1);
	}	
		
	hexdump("received packet", &buffer, ret);

	close(socket);

	rcode = (buffer[3] & 0x0F);

	//tempBuf[0] = buffer[4];
	//tempBuf[1] = buffer[5];
	//tempBuf[2] = '\0';
	
	//printf("%0x %0x %0x %0x\n", buffer[4], buffer[5], tempBuf[0], tempBuf[1]);

	//QDCOUNT = (uint16_t) strtol(tempBuf, NULL, 16);
	QDCOUNT = (uint16_t)  buffer[4] * 0x100 + buffer[5];
	printf("entries in question section: %u\n", QDCOUNT);
	ANCOUNT = (uint16_t)  buffer[6] * 0x100 + buffer[7];
	printf("records in answer section: %u\n", ANCOUNT);
	NSCOUNT = (uint16_t)  buffer[8] * 0x100 + buffer[9];
	printf("name server resource record count: %u\n", NSCOUNT);
	ARCOUNT = (uint16_t)  buffer[10] * 0x100 + buffer[11];
	printf("additional records count: %u\n", ARCOUNT);

	printf("query type: %u\n", dnsQuery.reqType);
	QCLASS = (uint16_t) dnsQuery.request[dnsQuery.length - 2] * 0x100 + dnsQuery.request[dnsQuery.length - 1];
	printf("query class: %u\n", QCLASS);
	length = dnsQuery.length + 1;	 // to skip 0xc00c
	ATYPE = (uint16_t) buffer[length + 1] * 0x100 + buffer[length + 2];
	printf("answer type: %u\n", ATYPE);
	ACLASS = (uint16_t) buffer[length + 3] * 0x100 + buffer[length + 4];
	printf("answer class: %u\n", ACLASS);
	TTL = (uint32_t) buffer[length + 5] * 0x1000000 + buffer[length + 6] * 0x10000 + buffer[length + 7] * 0x100 + buffer[length + 8];
	printf("seconds to cache: %u\n", TTL);
	RDLENGTH = (uint16_t) buffer[length + 9] * 0x100 + buffer[length + 10];
	printf("bytes in answer: %u\n", RDLENGTH);
	MSGID = (uint16_t) buffer[0] * 0x100 + buffer[1];
	printf("answer msg id: %u\n", MSGID);	
	
	

	if (rcode == 2) {
		printf("nameserver %s returned SERVFAIL:\n", SERVER);
		printf("  the name server was unable to process this query due to a\n  problem with the name server.\n");
		exit(1);
	} else if (rcode == 3) {
		printf("nameserver %s returned NXDOMAIN for %s:\n", SERVER, dnsQuery.url);
		printf("  the domain name referenced in the query does not exist\n");
		exit(1);
	}

  	/* search for and print IPv4 addresses */
	if (dnsQuery.reqType == 0x01) {
		printf("DNS server's answer is: (type#=%u):", ATYPE);
		//printf("IPv4 address(es) for %s:\n", dnsQuery.url);
		for (i = 0 ; i < ret ; i++) {
			if (buffer[i] == 0xC0 && buffer[i+3] == 0x01) {
				ip++; i += 12; /* ! += buf[i+1]; */
				printf(" %u.%u.%u.%u\n", buffer[i], buffer[i+1], buffer[i+2], buffer[i+3]);
			}
		}

		if (!ip) {
			printf("  No IPv4 address found in the DNS response!\n");
			exit(1);
		}
  	}
}


Output

dhanoopbhaskar@dhanoop-laptop:~/workspace/Copy/_works$ gcc dnsclient.c 
dhanoopbhaskar@dhanoop-laptop:~/workspace/Copy/_works$ ./a.out www.theinsanetechie.in
Asking DNS server 8.8.8.8 about www.theinsanetechie.in
parsing hostname: "www" is 3 characters
parsing hostname: "theinsanetechie" is 15 characters
parsing hostname: "in" is 2 characters
sending packet:
  0000  db 42 01 00 00 01 00 00 00 00 00 00 03 77 77 77  .B...........www
  0010  0f 74 68 65 69 6e 73 61 6e 65 74 65 63 68 69 65  .theinsanetechie
  0020  02 69 6e 00 00 01 00 01                          .in.....
received packet:
  0000  db 42 81 80 00 01 00 03 00 00 00 00 03 77 77 77  .B...........www
  0010  0f 74 68 65 69 6e 73 61 6e 65 74 65 63 68 69 65  .theinsanetechie
  0020  02 69 6e 00 00 01 00 01 c0 0c 00 05 00 01 00 00  .in.............
  0030  32 c7 00 10 03 67 68 73 06 67 6f 6f 67 6c 65 03  2....ghs.google.
  0040  63 6f 6d 00 c0 34 00 05 00 01 00 00 54 5f 00 08  com..4......T_..
  0050  03 67 68 73 01 6c c0 38 c0 50 00 01 00 01 00 00  .ghs.l.8.P......
  0060  01 2b 00 04 4a 7d 44 79                          .+..J}Dy
entries in question section: 1
records in answer section: 3
name server resource record count: 0
additional records count: 0
query type: 1
query class: 1
answer type: 5
answer class: 1
seconds to cache: 12999
bytes in answer: 16
answer msg id: 56130
DNS server's answer is: (type#=5): 74.125.68.121

dhanoopbhaskar@dhanoop-laptop:~/workspace/Copy/_works$ 

Thursday, January 7, 2016

Renewed IEEE membership :)

 

Contact Form

Name

Email *

Message *