• Enter Slide 1 Title Here

    This is slide 1 description. Go to Edit HTML of your blogger blog. Find these sentences. You can replace these sentences with your own words.

  • Enter Slide 2 Title Here

    This is slide 2 description. Go to Edit HTML of your blogger blog. Find these sentences. You can replace these sentences with your own words.

  • Enter Slide 3 Title Here

    This is slide 3 description. Go to Edit HTML of your blogger blog. Find these sentences. You can replace these sentences with your own words.

Tuesday, September 19, 2017

Transfer domain to namecheap in 2 steps


Transferring domains from any registrar to namecheap is quite simple and straightforward and involves only 2 steps. I am writing this to express how happy I am, on my digizol.com domain transfer experience. Before looking at the steps, let's check motivational factors behind my decision on transferring the domain to namecheap.

Motivations for namecheap

I had few motivations compared to my previous domain registrar.
  1. Ease of use & great customer service rumor
    • Yes, this rumor proved true in my transfer experience
  2. Username is my email address
    • Seriously! my previous domain registrar used a 7 digit number to identify me & I could never remember it. I believe it to be a security feature, but I am not happy with that approach.
  3. Originally paid remaining period is carried forward
    • For my transfer, the expiry date was set including the remaining duration in previous registra. Read more details here
  4. Namecheap promotions for transfers
    • With that, the cost is $ 9.02 at the time I did the transfer
  5. Free Whois protection
    • This is free and saves some money but only for the first year, so I do not count this as a motivation. 

Steps in domain transfer

As mentioned above, this has only two steps.

Step 1 - Follow the straightforward UI

Search for the domain name, click transfer & follow the simple UI. I am not listing down the details as the steps are straightforward.

Step 2 - Chat with online support members

From the point you get stuck or looking for some help, simply use the support. The online chat support is extremely good, I would call it a rockstar. They will stay with you online and do all the needed configurations/changes and instructs on anything to be done on previous registrar's end. You chat will be completed only when everything is in place; at least that is how it ended for me 😄.

Disclaimer: I am not an employee of namecheap.com

Thursday, August 24, 2017

Without root/sudo permission install Node.js on Linux/CentOS

Node.js is a free and open source JavaScript runtime for server side programming. For *nix environments, users can do installations with RPMs or via package managers like yum. However, most often developers face restrictions during installation due to the need of root permission for directories like "/usr/local/bin". Here, we will be installing Node.js inside a directory under user_home.

1. Download binary distribution

Latest binaries can be downloaded from Node.js official release directory.

https://nodejs.org/download/release/
For CentOS 6.7, I downloaded Linux 64-bit binary of latest version (8.4.0) from below link.
https://nodejs.org/download/release/v8.4.0/node-v8.4.0-linux-x64.tar.gz
Make sure to pick suitable binary for your installation.

2. Extract into installation directory

This binary file must be extracted into the directory that you are installing Node.js. In my machine, I extracted it into below directory.
/home/user/software/nodejs_v8.4.0/

3. Add Node.js to PATH

It is required to append Node.js installation to PATH variable. For that, you can update either ~/.bash_profile or ~/.bashrc file as below.

export NODEJS_HOME=/home/user/software/nodejs_v8.4.0
export PATH=$PATH:$NODEJS_HOME/bin

4. Verify installation

Open up a console and check Node.js version to verify the installation as below.

bash$ node --version
v8.4.0
If you see the installed version as v8.4.0, that confirms the installation is completed. For this we did not use any additional *inx user privileges.

Related Articles

Tuesday, August 22, 2017

[Solved] Nginx - error: HTTP rewrite module requires the PCRE library

Nginx $ ./configure: error: the HTTP rewrite module requires the PCRE library. While trying to install Nginx server using the source distribution, "./configure" command failed on CentOS 6.7 with below error message. It complains that PCRE library is not available on the system.

./configure: error: the HTTP rewrite module requires the PCRE library.
You can either disable the module by using
--without-http_rewrite_module option, or
install the PCRE library into the system,
or build the PCRE library statically from
the source with nginx by using --with-pcre=<path> option.

Solution

You can install this library either via command line or GUI.

Resolve via Command line

yum install pcre-devel

Resolve via GUI

Go to "System" -> "Administration" -> "Add/Remove Software" as shown below.

Then search for "pcre-devel", select "Development files for pcre" and install by clicking "Apply" as shown below.
After that, you can rerun the "./configure" command to continue installing Nginx 1.12.1 server.
Hope this helps.

Related Articles

Tuesday, July 25, 2017

[Tutorial] Plotly graph drawing in Java webapp - Part 2

Plotly Javascript library supports generating various charts. Java Servlet & JSP based web applications can use it to display graphical representations of data.

In this tutorial, you will learn to include graphs into a simple Java web application. Image above shows the graph generated at the end of the tutorial. Complete project is already moved to github for your references.

This tutorial consists of two parts.

Part 1

First step is to create a simple web application with index.jsp that can submit a user entered parameter to a Servlet which is redirecting the user back to original index.jsp.

Part 2

Here the servlet is modified to return some data (collection of Customer objects) and index.jsp is modified to draw a chart using that data.

Note: If you are not that familiar with Java web applications, I recommend you to start with previous Part 1 of this tutorial before moving further.

Part 2

Java web application project structure in Part 1 must be modified as shown in below image.

Servlet Changes

Servlet class must return a list of Customers to the index.jsp. For that, a simple Customer class and a modification to Servlet is needed.

1. Create a Customer class

This class is used to represent the data send to index.jsp from CustomerServlet. It has an id as well as age & salesCount.

package com.digizol.webapp.plotly;

public class Customer {

private String id;
private int age;
private int salesCount;

public Customer(String id, int age, int salesCount) {
this.id = id;
this.age = age;
this.salesCount = salesCount;
}

public String getId() {
return id;
}
public int getAge() {
return age;
}
public int getSalesCount() {
return salesCount;
}
}

2. CustomerServlet returning Customer object list

doGet() method is modified to return a list of Customer objects. This class has 10 Customer objects. Size of returned list will be based on the 'size' request parameter submitted via index.jsp. This Servlet will return that list as "customersList" to index.jsp.

package com.digizol.webapp.plotly;

import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;
import java.util.*;

public class CustomerServlet extends HttpServlet {

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

System.out.println("Parameter [size] value = " + request.getParameter("size"));
// return a customers list to index.jsp
request.setAttribute("customersList",
getCustomers(resultSize(request.getParameter("size"))));
request.getRequestDispatcher("/index.jsp").forward(request, response);
}

private List<Customer> customers = new ArrayList<Customer>();

public CustomerServlet() {
initCustomersList();
}

private int resultSize(String sizeParam) {
return sizeParam==null?customers.size():Integer.parseInt(sizeParam);
}

private List<Customer> getCustomers(int size) {
return customers.subList(0, size);
}

private void initCustomersList() {
customers.add(new Customer("cust-1", 25, 17));
customers.add(new Customer("cust-2", 36, 99));
customers.add(new Customer("cust-3", 17, 0));
customers.add(new Customer("cust-4", 58, 10));
customers.add(new Customer("cust-5", 49, 32));
customers.add(new Customer("cust-6", 80, 14));
customers.add(new Customer("cust-7", 31, 78));
customers.add(new Customer("cust-8", 22, 89));
customers.add(new Customer("cust-9", 43, 21));
customers.add(new Customer("cust-10", 74, 45));
}
}

3. Get plotly javascript

Download the plotly-latest.min.js Javascript file from here. Place this file under src/main/webapp/plotly/js directory as shown in image.

4. index.js Changes

index.js file needs below changes.

1. Add plotly javascript file to index.jsp
2. Javascript function to draw chart
3. Add a DIV for chart
4. Update index.jsp to organize data for Javascript
5. Update index.jsp to draw chart

Fully completed index.jsp page code looks as below, do not worry. Each change is explained in details after the code.

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html>

<head>
<title>Customer Information Center</title>
<script src="plotly/js/plotly-latest.min.js" type="text/javascript"></script>

<script type="text/javascript">
function plotChart(elementId, data, layout) {
Plotly.newPlot(document.getElementById(elementId),
data, layout, {displayModeBar: false});
}
</script>
</head>

<body>

<div style="background:#ffffee; text-align:center; padding-bottom:2px">
<h1>Customer Information Center</h1>

Draw customer information graph.<p/>

<form action="customers" method="get">

Results size:
<select name="size">
<option value="5">5</option>
<option value="10">10</option>
</select>
<p/>
<button style="padding:5px">Draw Chart</button>
</form>
</div>

<c:if test="${not empty customersList}">

<h2>Age and Sales Count Chart</h2>

<div id="customersChart" ></div>

<script>

var customerAges = {
name: 'Age',
type: 'lines+markers',
line: { width: 6},
marker: { size: 8}
};
var customerSalesCount = {
name: 'Sales Count',
type: 'lines+markers',
line: { width: 3},
marker: { size: 4}
};
var age_X = new Array();
var age_Y = new Array();
var sales_count_X = new Array();
var sales_count_Y = new Array();

<c:forEach items="${customersList}" var="customer" varStatus="i">
age_X[${i.index}] = "${customer.id}";
age_Y[${i.index}] = "${customer.age}";

sales_count_X[${i.index}] = "${customer.id}";
sales_count_Y[${i.index}] = "${customer.salesCount}";
</c:forEach>

customerAges.x = age_X;
customerAges.y = age_Y;

customerSalesCount.x = sales_count_X;
customerSalesCount.y = sales_count_Y;

var data = [customerAges, customerSalesCount];
var layout = {
xaxis: {
title: 'ID',
showgrid: true,
zeroline: true,
},
yaxis: {
showgrid: true,
showline: true,
zeroline: true,
}
};

plotChart("customersChart", data, layout);
</script>
</c:if>

</body>
</html>
Each change has a specific reason.

1. Add plotly javascript file to index.jsp

A reference to plotly Javascript file is placed within <head> tags of index.jsp as below.

<head>
<title>Customer Information Center</title>
<script src="plotly/js/plotly-latest.min.js" type="text/javascript"></script>
</head>
2. Javascript function to draw chart
Write a simple function named "plotChart" to draw graphs using plotly as follows inside <head> tag of index.jsp

<head>
<title>Customer Information Center</title>
<script src="plotly/js/plotly-latest.min.js" type="text/javascript"></script>

<script type="text/javascript">
function plotChart(elementId, data, layout) {
Plotly.newPlot(document.getElementById(elementId),
data, layout, {displayModeBar: false});
}
</script>
</head>
3. Add a DIV for chart

It is required to provide an empty DIV element for plotly to generate the chart.

<div id="customersChart" ></div>
4. Update index.jsp to organize data for Javascript
index.jsp page must iterate through the list of Customer objects returns from CustomerServlet as "customersList". Then, Javascript objects must be populated using that data in order to generate the graphs.

As Customer has two attributes age & salesCount, it is possible to draw two lines in one chart. As shown below, x & y properties of customerAges and customerSalesCount must be populated correctly.

var customerAges = {
name: 'Age',
type: 'lines+markers'
};
var customerSalesCount = {
name: 'Sales Count',
type: 'lines+markers',
};
var age_X = new Array();
var age_Y = new Array();
var sales_count_X = new Array();
var sales_count_Y = new Array();


age_X[${i.index}] = "${customer.id}";
age_Y[${i.index}] = "${customer.age}";

sales_count_X[${i.index}] = "${customer.id}";
sales_count_Y[${i.index}] = "${customer.salesCount}";


customerAges.x = age_X;
customerAges.y = age_Y;

customerSalesCount.x = sales_count_X;
customerSalesCount.y = sales_count_Y;
5. Update index.jsp to draw chart

Using customerAges & customerSalesCount Javascript objects, invoke plotChart() method to generate a chart inside "customersChart" div.

var data = [customerAges, customerSalesCount];
var layout = {
xaxis: {
title: 'ID'
},
yaxis: {
showgrid: true
}
};

plotChart("customersChart", data, layout);

Final Result

Below is the final outcome of the application after building & deploying. It shows two line graphs, for age and sales count.



Hope this helps.

Draw graphs in Java webapp with Plotly - Tutorial

Plotly Javascript library supports generating various charts. Java Servlet & JSP based web applications can use it to display graphical representations of data.

In this tutorial, you will learn to include graphs into a simple Java web application. Image above shows the graph generated at the end of the tutorial. Complete project is already moved to github for your references.

This tutorial consists of two parts.

Part 1

First step is to create a simple web application with index.jsp that can submit a user entered parameter to a Servlet which is redirecting the user back to original index.jsp.

Part 2

Here the above servlet is modified to return some data (collection of Customer objects) and index.jsp is modified to draw a chart using those data.

Note: If you are familiar with Java web applications, you can jump to Part 2 directly.

Part 1

1. Build a simple web application

This project contains only one JSP page and a Servlet. JSP is used to display a form & a chart while the Servlet is used to generate raw data for the chart.

First create the Java web application project structure as shown in image.

An index.jsp and a CustomerServlet with web.xml for a simple web application. It also has a pom.xml for the build.

CustomerServlet

doGet() method prints the size parameter in the request; then forwards the request to index.jsp page.

package com.digizol.webapp.plotly;

import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;

public class CustomerServlet extends HttpServlet {

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

System.out.println("Parameter [size] value = " + request.getParameter("size"));
request.getRequestDispatcher("/index.jsp").forward(request, response);
}
}

web.xml

This is the file that configures Servlet related information. Here URL "/customers" is mapped to CustomerServlet.

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">

<servlet>
<servlet-name>customers</servlet-name>
<servlet-class>com.digizol.webapp.plotly.CustomerServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>customers</servlet-name>
<url-pattern>/customers</url-pattern>
</servlet-mapping>

</web-app>

index.jsp

This has the ability to submit the results size to "/customers" URL which actually is received by CustomerServlet.

<html>
<body>
<div>
<h1>Customer Information Center</h1>
Draw customer information graph.<p/>
<form action="customers" method="get">
Results size:
<select name="size">
<option value="5">5</option>
<option value="10">10</option>
</select>
<p/>
<button style="padding:5px">Draw Chart</button>
</form>
</div>
</body>
</html>
Clicking on "Draw Chart" button caused the doGet() method to be invoked on CustomerServlet.

pom.xml

Maven build file is used to generate the WAR file including the libraries.

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">

<modelVersion>4.0.0</modelVersion>
<groupId>com.digizol.webapp.plotly</groupId>
<artifactId>webapp-with-plotly</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>webapp-with-plotly maven webapp</name>

<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>

<build>
<finalName>customers-plotly</finalName>
</build>

</project>

2. Build & Deploy

With Maven 3.*, you can build the project using "mvn clean package" command. Deployable customers-plotly.war is generated inside target folder.

Copy customers-plotly.war into webapps directory of a Tomcat deployment and start Tomcat server.

Use below URL to see the web page & try clicking "Draw Chart" button.

http://localhost:8080/customers-plotly



Adding charts to this webpage is covered in Part 2.

Tuesday, November 19, 2013

[Eclipse] How to use local DTDs to validate XMLs

By default Eclipse does not support local DTD files. Because of this, many developers loose a privilege of Eclipse; content assistance for parameter/attribute is missing while working with DTD based XML files. However if you are connected to Internet, you will not face this issue.

Here is a tip to show you how to point your Eclipse instance to local DTD files.

1. Add XML Catalogs

First you need to open up the "XML Catalog" dialog by:
Windows -> Preferences -> XML -> XML Catalog
Then click on "Add..." and select "Catalog Entry". For a single local DTD file you need to add one Catalog Entry.

For the location: you need to find DTD file from your local disk.
For the Key: you need to enter the relevant key as per the <!DOCTYPE entry of your XML files.

2. Hibernate Examples Demo

This tip is demoed using Hibernate as an example. Hibernate Configuration DTD and Hibernate Mappings DTD is added locally into Eclipse below. First of all, you need to download and store hibernate jar file somewhere in your local disk; we used hibernate-core-3.6.10.Final version (available here as well as here).

2.1 Hibernate Configuration DTD

DTD file referred by hibernate.cfg.xml file is "hibernate-configuration-3.0.dtd". To point eclipse to that DTD, you need to enter below values and select OK in above "Catalog Entry" screen.


Key: -//Hibernate/Hibernate Configuration DTD 3.0//EN
Location: jar:file:/<path/to/jar>/hibernate-core.jar!/org/hibernate/hibernate-configuration-3.0.dtd

Then Eclipse will create a new Catalog and save with below details.

Entry element: Public
Location: org/hibernate/hibernate-configuration-3.0.dtd in jar file opt/libs/hibernate-core.jar
URI: jar:file:/opt/libs/hibernate-core.jar!/org/hibernate/hibernate-configuration-3.0.dtd
Key type: Public ID
Key: -//Hibernate/Hibernate Configuration DTD 3.0//EN

2.2 Hibernate Mappings DTD

DTD file referred by <entity>.hbm.xml file is "hibernate-mapping-3.0.dtd". Same as above step, in "Catalog Entry" screen you need to enter below values and select OK.

Eclipse will create a new Catalog and save with below details.

Entry element: Public
Location: org/hibernate/hibernate-mapping-3.0.dtd in jar file opt/libs/hibernate-core.jar
URI: jar:file:/opt/libs/hibernate-core.jar!/org/hibernate/hibernate-mapping-3.0.dtd
Key type: Public ID
Key: -//Hibernate/Hibernate Mapping DTD 3.0//EN

2.3 Results


After creating the Catalogs, you can check this my opening your hibernate.cfg.xml file and trying to open up the DTD file link in the top of the file by "Ctrl + Mouse Over". You will notice that Eclipse prompts two links and one is the local DTD.

Similarly, Eclipse will provide content assistance for XML file editing even when internet connectivity is gone.

3. Conclusion

Using this method, you can create catalogs for any DTD and let Eclipse point to your local DTD files. Hope this helps you.

Thursday, November 7, 2013

[Eclipse] Exporting & Importing Launch configurations

Many Eclipse "Launch Configuration" created has so much details; OSGi configurations for instance. So there arises a requirement of exporting the launch configurations and later importing them into other Eclipse workspaces. Interestingly, Eclipse has an import/export feature for "Launch Configuration"; which is quite simple but handy. I believe some software developers are not taking the advantage of this.

Here are the steps to follow.

1. Exporting Configurations

First you need to select:
  File -> Export...
Then select:
  Run/Debug -> Launch Configurations

Then you will see a view with all available launch configurations as shown below. You can select the configurations you need to export. You need a provide a location to store the exported configurations.

Each configuration will be saved into separate XML files, but with the extension as ".launch".

2. Importing Configurations

Similar to export, first you need to select:
  File -> Import...
Then select:
  Run/Debug -> Launch Configurations

Then you will see a view where you can select a directory with ".launch" files. When that folder is selected, available launch configurations will be displayed in the UI; so that you can select which ones to be imported as shown below.

3. Sample .launch file

Below is the exporter file for the OSGi launch configuration we created for Eclipse Kepler 4.3.1.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.pde.ui.EquinoxLauncher">
<booleanAttribute key="append.args" value="true"/>
<booleanAttribute key="automaticAdd" value="true"/>
<booleanAttribute key="automaticValidate" value="false"/>
<stringAttribute key="bootstrap" value=""/>
<stringAttribute key="checked" value="[NONE]"/>
<booleanAttribute key="clearConfig" value="false"/>
<stringAttribute key="configLocation" value="${workspace_loc}/.metadata/.plugins/org.eclipse.pde.core/Multi-Management-App"/>
<booleanAttribute key="default" value="true"/>
<booleanAttribute key="default_auto_start" value="true"/>
<intAttribute key="default_start_level" value="4"/>
<booleanAttribute key="includeOptional" value="true"/>
<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="true"/>
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog -console"/>
<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Declipse.ignoreApp=true -Dosgi.noShutdown=true"/>
<stringAttribute key="pde.version" value="3.3"/>
<booleanAttribute key="show_selected_only" value="true"/>
<stringAttribute key="target_bundles" value="org.apache.felix.gogo.command@default:default,org.apache.felix.gogo.runtime@default:default,org.apache.felix.gogo.shell@default:default,org.eclipse.equinox.console@default:default,org.eclipse.osgi@-1:true"/>
<booleanAttribute key="tracing" value="false"/>
<booleanAttribute key="useCustomFeatures" value="false"/>
<booleanAttribute key="useDefaultConfigArea" value="true"/>
<stringAttribute key="workspace_bundles" value="com.digizol.osgi.multiservice.english@default:default,com.digizol.osgi.multiservice.sinhala@default:default,com.digizol.osgi.multiservice@default:default,com.digizol.osgi.baseservice@default:default"/>
</launchConfiguration>

Hope this helps you.

Wednesday, November 6, 2013

[Eclipse] org.osgi.framework.BundleException: Could not find bundle: org.eclipse.equinox.console

With latest Eclipse Kepler 4.3.1 SR1, I tried to run one of my older OSGi projects. Earlier this project was running smoothly with Eclipse Indigo (3.7.1).

However, when I tried to execute it via Eclipse Kepler version as a "OSGI Framework" configuration; I was surprised since it showed an exception as org.osgi.framework.BundleException: Could not find bundle: org.eclipse.equinox.console .

Below is the complete stack-trace.

!SESSION date time -----------------------------------------------
eclipse.buildId=unknown
java.version=1.6.0_26
java.vendor=Sun Microsystems Inc.
BootLoader constants: OS=linux, ARCH=x86, WS=gtk, NL=en_US
Command-line arguments: -dev file:$Location/dev.properties -os linux
-ws gtk -arch x86 -consoleLog -console

!ENTRY org.eclipse.osgi 4 0 date time
!MESSAGE Could not find bundle: org.eclipse.equinox.console
!STACK 0
org.osgi.framework.BundleException: Could not find bundle: org.eclipse.equinox.console
at org.eclipse.osgi.framework.internal.core.ConsoleManager.checkForConsoleBundle(ConsoleManager.java:211)
at org.eclipse.core.runtime.adaptor.EclipseStarter.startup(EclipseStarter.java:298)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:177)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:636)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:591)
at org.eclipse.equinox.launcher.Main.run(Main.java:1450)
at org.eclipse.equinox.launcher.Main.main(Main.java:1426)

Solution

A quick look into the details revealed that the default shell of Eclipse has been moved to "Apache Felix Gogo"; so the necessary bundles must be added to the "Run Configuration" before running. Followings are the four bundled that you need to select from the list.

org.apache.felix.gogo.command_0.10.0v<version>.jar
org.apache.felix.gogo.runtime_0.10.0v<version>.jar
org.apache.felix.gogo.shell_0.10.0v<version>.jar
org.eclipse.equinox.console_1.0.100<version>.jar

After adding these as shown in the above diagram, the program runs smoothly.

For more details on the changes on OSGi shell, please refer here.

Monday, November 4, 2013

OSGi Console of Eclipse Kepler 4.3.1

Eclipse IDE is developed based on OSGi plugin architecture, but I had not seen the list of OSGi bundles that are used in my Eclipse installation. Today I noticed that there is a way to find the list of bundled used, and it is quite simple. So I thought of sharing it with you.

I am running Eclipse version 4.3.1 (JEE Kepler). First we need to open the OSGi console of the running Eclipse instance. For that we need to open up the 'Console view' first via:

Window -> Show view -> Console

Then you need to select "Host OSGi Console" on the sub-toolbar in this Console view as shown in the image below.
As soon as you go to this console view, you will see below WARNING, which is quite OK since our intention is also to connect to the running instance of Eclipse.
WARNING: This console is connected to the current running instance of Eclipse!
osgi>

If you are already familiar with OSGi console in OSGi software development, then most likely you know how to find details about the plugins. However even if you are new to OSGi, no need to worry. You simple have to enter "ss" command in this console to see the list of bundles with id and state. I got a list of 822 plugins and below is a trimmed down version of the output I received.

WARNING: This console is connected to the current running instance of Eclipse!
osgi> ss
"Framework is launched."


id State Bundle
0 ACTIVE org.eclipse.osgi_3.9.1.v20130814-1242
1 ACTIVE org.eclipse.equinox.simpleconfigurator_1.0.400.v20130327-2119
2 RESOLVED ch.qos.logback.classic_1.0.7.v20121108-1250
Fragments=525
3 RESOLVED ch.qos.logback.core_1.0.7.v20121108-1250
4 RESOLVED ch.qos.logback.slf4j_1.0.7.v20121108-1250
Master=817
5 ACTIVE com.ibm.icu_50.1.1.v201304230130
6 RESOLVED com.jcraft.jsch_0.1.46.v201205102330
7 RESOLVED com.ning.async-http-client_1.6.5.20130531-2315
8 RESOLVED com.sun.el_2.2.0.v201303151357
9 RESOLVED com.sun.syndication_0.9.0.v200803061811
10 RESOLVED java_cup.runtime_0.10.0.v201005080400
11 RESOLVED javaewah_0.5.6.v201307211000
12 RESOLVED javax.activation_1.1.0.v201211130549
13 RESOLVED javax.annotation_1.1.0.v201209060031
14 RESOLVED javax.el_2.2.0.v201303151357
15 RESOLVED javax.inject_1.0.0.v20091030
16 RESOLVED javax.jws_2.0.0.v201005080400
17 RESOLVED javax.mail_1.4.0.v201005080615
18 RESOLVED javax.persistence_2.1.0.v201304241213
19 RESOLVED javax.servlet_3.0.0.v201112011016
20 RESOLVED javax.servlet.jsp_2.2.0.v201112011158
21 RESOLVED javax.wsdl_1.6.2.v201012040545
22 RESOLVED javax.wsdl_1.5.1.v201012040544
23 RESOLVED javax.xml_1.3.4.v201005080400
24 RESOLVED javax.xml.bind_2.1.9.v201005080401
25 RESOLVED javax.xml.rpc_1.1.0.v201209140446
26 RESOLVED javax.xml.soap_1.2.0.v201005080501
27 RESOLVED javax.xml.stream_1.0.1.v201004272200
28 RESOLVED javax.xml.ws_2.1.0.v200902101523
29 RESOLVED net.sourceforge.lpg.lpgjavaruntime_1.1.0.v201004271650
30 RESOLVED org.apache.ant_1.8.4.v201303080030
31 RESOLVED org.apache.axis_1.4.0.v201005080400
32 RESOLVED org.apache.batik.css_1.6.0.v201011041432
33 RESOLVED org.apache.batik.util_1.6.0.v201011041432
34 RESOLVED org.apache.batik.util.gui_1.6.0.v201011041432
35 RESOLVED org.apache.bcel_5.2.0.v201005080400
36 RESOLVED org.apache.commons.codec_1.4.0.v201209201156
37 RESOLVED org.apache.commons.collections_3.2.0.v2013030210310
38 RESOLVED org.apache.commons.discovery_0.2.0.v201004190315
39 RESOLVED org.apache.commons.httpclient_3.1.0.v201012070820
40 RESOLVED org.apache.commons.io_2.0.1.v201105210651
41 RESOLVED org.apache.commons.lang_2.6.0.v201205030909
42 RESOLVED org.apache.commons.logging_1.1.1.v201101211721
43 RESOLVED org.apache.commons.logging_1.0.4.v201101211617
44 RESOLVED org.apache.commons.net_3.2.0.v201305141515
45 ACTIVE org.apache.felix.gogo.command_0.10.0.v201209301215
46 ACTIVE org.apache.felix.gogo.runtime_0.10.0.v201209301036
47 ACTIVE org.apache.felix.gogo.shell_0.10.0.v201212101605
48 RESOLVED org.apache.httpcomponents.httpclient_4.1.3.v201209201135
49 RESOLVED org.apache.httpcomponents.httpcore_4.1.4.v201203221030
50 RESOLVED org.apache.jasper.glassfish_2.2.2.v201205150955
51 RESOLVED org.apache.log4j_1.2.15.v201012070815
52 RESOLVED org.apache.lucene.analysis_3.5.0.v20120725-1805
53 RESOLVED org.apache.lucene.core_3.5.0.v20120725-1805
54 RESOLVED org.apache.velocity_1.5.0.v200905192330
55 RESOLVED org.apache.ws.commons.util_1.0.1.v20100518-1140
56 RESOLVED org.apache.wsil4j_1.0.0.v200901211807
57 RESOLVED org.apache.xalan_2.7.1.v201005080400
58 RESOLVED org.apache.xerces_2.9.0.v201101211617
59 RESOLVED org.apache.xml.resolver_1.2.0.v201005080400
60 RESOLVED org.apache.xml.serializer_2.7.1.v201005080400
61 RESOLVED org.apache.xmlrpc_3.0.0.v20100427-1100
62 STARTING org.eclipse.ant.core_3.2.500.v20130402-1746
63 STARTING org.eclipse.ant.launching_1.0.300.v20130514-1341
64 STARTING org.eclipse.ant.ui_3.5.400.v20130514-1341
65 STARTING org.eclipse.compare_3.5.401.v20130709-1308
66 STARTING org.eclipse.compare.core_3.5.300.v20130514-1224
67 RESOLVED org.eclipse.core.commands_3.6.100.v20130515-1857

...

818 RESOLVED org.sonatype.m2e.mavenarchiver_0.15.0.201207090125-signed-20130612210623
819 RESOLVED org.uddi4j_2.0.5.v200805270300
820 RESOLVED org.w3c.css.sac_1.3.1.v200903091627
821 RESOLVED org.w3c.dom.smil_1.0.0.v200806040011
822 RESOLVED org.w3c.dom.svg_1.1.0.v201011041433
osgi>
If you are interested in finding further details about these OSGi bundles, you can enter 'help' in the OSGi console and find the list of commands to try out.

[Ubuntu] Multiple launchers for each individual Eclipse installation

I have multiple Eclipse versions installed in my Ubuntu 12.04, so I wanted to have separate launcher icons in Launchpad. However I noticed it is not possible to create launch icons simply using:
"Right click -> Lock to Launcher" approach since the same launcher icon is used for all Eclipse installations; simply said there will be only one launcher icon for all Eclipse installations. 


It is quite easy to create multiple launcher icons for multiple installations. Below is the 4 steps you need to follow.

1. Create <eclipse-name>.desktop files for each installation

I created eclipse-jee-kepler.desktop file inside Kepler Eclipse installation folders, but you use any preferred location.

2. Update <eclipse-name>.desktop file with information

For "Eclipse JEE Kepler" installation, add the below content to eclipse-jee-kepler.desktop. You will have to change the path to the executable eclipse file.
[Desktop Entry]
Version=4.3.1
Name=Eclipse JEE Kepler
Comment=Eclipse JEE Kepler
Exec=/<path>/eclipse-jee-kepler-SR1-linux-gtk/eclipse
Icon=/<path>/eclipse-jee-kepler-SR1-linux-gtk/eclipse.ico
StartupNotify=false
Terminal=false
Type=Application
Categories=Development

You can create an eclipse.ico file to be displayed in the Launchpad yourself. As displayed here, I have created a simple file for my usage.

3. Grant permission to execute

Right click on this eclipse-jee-kepler.desktop file and select "Properties". Then go to the "Permissions" tab and select execute permission as shown in the image.

4. Run the eclipse installation

You can double click on the eclipse-jee-kepler.desktop file to start your eclipse installation. When this eclipse installation is started, the provided eclipse.ico will be displayed in the Launchpad. Now you can create a launch icon simply using "Right click -> Lock to Launcher".

Finally...

For each of your eclipse installations, you can create separate files with above 4 steps; then replace the property values to match with each eclipse installations (including a separate .ico).

If you are interested in finding more information about Unity Launchers and Desktop files, you can refer here.

Saturday, November 2, 2013

[Java] String format against opening & closing characters

How to validate the format of a given string according to a given set of opening-closing character pairs? This has been raised as an interview question, so I thought of writing a simple program to solve this.

Let me elaborate the question. There are characters that are considered as opening characters and closing characters; when '(' is an opening character, the relevant closing character is ')' For example; ([]) is correctly formatted, but ([) is not. So your task is to find out whether all the starting characters are properly ended with a ending character.

Here, I am using a Stack (java.util.Stack) to solve the problem.

GroupingPair class

A simple class named GroupingPair is written to hold pair of opening and closing characters. For instance, '[' for starting and ']' for ending.
package com.digizol.interviews.string.format;

public class GroupingPair {

private Character start;
private Character end;

public GroupingPair(Character start, Character end) {
this.start = start;
this.end = end;
}

public Character getStart() {
return start;
}

public Character getEnd() {
return end;
}
}

FormatValidator class

This class has implemented the logic using a stack. This can be initialized with a list of GroupingPair objects. Then a given strings each character is compared against the GroupingPair objects to find out whether there is an opening or closing characters. If an opening character is found, related GroupingPair instance is pushed to the stack. Similarly, if a closing tag is found, the top GroupingPair is popped and compared with the character to see whether it matches with the expected.
package com.digizol.interviews.string.format;

import java.util.HashMap;
import java.util.Map;
import java.util.Stack;

public class FormatValidator {

private Map<Character, GroupingPair> openingChars;
private Map<Character, GroupingPair> closingChars;

public FormatValidator(GroupingPair[] pairs) {
initOpeningCharacters(pairs);
initClosingCharacters(pairs);
}

private void initClosingCharacters(GroupingPair[] pairs) {
closingChars = new HashMap<Character, GroupingPair>();
for (GroupingPair pair: pairs) {
closingChars.put(pair.getEnd(), pair);
}
}

private void initOpeningCharacters(GroupingPair[] pairs) {
openingChars = new HashMap<Character, GroupingPair>();
for (GroupingPair pair: pairs) {
openingChars.put(pair.getStart(), pair);
}
}

public boolean validate(String string) {
return validate(string, false);
}

public boolean validate(String string, boolean validateOtherCharacters) {

Stack<GroupingPair> stack = new Stack<GroupingPair>();

char[] characterArray = string.toCharArray();

for (Character c: characterArray) {

if (openingChars.containsKey(c)) {
stack.push(openingChars.get(c));
} else if (closingChars.containsKey(c)) {
if (!c.equals(stack.pop().getEnd())) {
return false;
}
} else if (validateOtherCharacters) {
System.out.println("Unexpected character '" + c + "' found in string: " + string);
return false;
}
}
return stack.isEmpty();
}
}

Test class

This is a simple class with the main method to test few examples. Character pairs (), '<'>' and [] are given for initialization.
package com.digizol.interviews.string.format;

public class Test {

public static void main(String[] args) {

FormatValidator validator = new FormatValidator(createPairs());

String[] toTest = { "[(])",
"([<>])",
"([)",
"()[]<>",
"(()[]<>)",
"(mal [ formatted )",
"(this [ is < well > formatted ] text)"
};

for (String string : toTest) {

boolean valid = validator.validate(string, false);

if (valid) {
System.out.println(string + " \t-> well formatted");
} else {
System.out.println(string + " \t-> malformed");
}
}
}

private static GroupingPair[] createPairs() {
GroupingPair[] pairs = new GroupingPair[] {
new GroupingPair('(', ')'),
new GroupingPair('<', '>'),
new GroupingPair('[', ']')
};
return pairs;
}
}

Following is the output you will get when this Test class is executed.
[(]) -> malformed
([<>]) -> well formatted
([) -> malformed
()[]<> -> well formatted
(()[]<>) -> well formatted
(mal [ formatted ) -> malformed
(this [ is < well > formatted ] text) -> well formatted

As you can see, the program has identified whether a string is well formatted or not. This eclipse project is available for download.

Monday, October 28, 2013

[Jenkins] Automatically retry a failed build

Are your Jenkins builds failing due to unavoidable reasons like unavailability of external databases, file systems etc? The only solution you might be having right now is to reschedule the build after fixing that external issue. In this post, I will be discussing on how you can automatically rerun a failed build.

Setup

For this, we are going to use a plugin named Naginator, version 1.8 is available here for download. As the first step, please install this plugin into your Jenkins.

When it is installed, there will be a new action named "Retry build after failure" added to the post-build action list in job configuration page (as shown).

Configuration

First create a new job. If you need to retry an existing job, please open the job configuration page. Then click on the "Add post-build action" button and select "Retry build after failure". This will add a new configuration section as shown in the below image.


There are 3 configuration settings (as numbered in above image). Let's discuss each in details below.

Setting 1 -> Rerun build for unstable builds as well as failures

This option is there to indicate whether you should be retrying the UNSTABLE state builds as well in addition to FAILURE state builds. Let's set it to true.

Setting 2 -> Delay before schedule

This allows you to define how long to delay a retrying build start-time from the time it was failed. There are two options to choose from; one is to provide a "fixed period" and the other is to provide an "increasing period". Let's use fixed period; and set 300 there (meaning 5 mins).

Setting 3 -> Max number of successive failed build

This is used to control the number of continuous failure builds. Jenkins will not automatically retry more than this maximum number of consecutive failures. So let's set 2 there so that it is retried only two times.

Conclusion

As expected, this is working without any issues and stops retrying as soon as the build is successful. Hope this will help you in avoiding manual retries.

Wednesday, October 16, 2013

[Log4j] How to integrate with your Java project

This is a quick guide on how to use log4j in your Java project. This task requires only five simple steps listed below. Each of these step is explained in details below.

  1. Set up the project with log4j
  2. Create log4j.properties file
  3. Write a class to record log messages
  4. Compile and run program
  5. Check the log messages

1. Set up the project with log4j

As the first step, let's download the log4j 1.2.17 latest archive (tar or zip). When you extract the archive, log4j-1.2.17.jar file is available in the root of the directory.

Let's create a new project named say log4j-helloworld and copy the log4j-1.2.17.jar into a folder named lib inside the project.

2. Create log4j.properties file

Next task is to create a log4j.properties file (shown below) inside the project folder. This file is the configuration file that provides how, where, which etc instructions on generating log messages.


# root level configurations
log4j.rootLogger=INFO,console,file

# configuration for console outputs
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout

# configuration for file output (into a file named messages.log)
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=messages.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout

# threshold for file output
log4j.appender.file.Threshold=ERROR

3. Write a class to record log messages

Let's write a simple class named Main (in src folder) with a main method to generate some log statements. Logger is added to the class as an attribute and used to write logs of different levels like debug, info and error.

package com.digizol.log4j.helloworld;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;

public class Main {

private static Logger log = Logger.getLogger(Main.class);

public static void main(String[] args) {

log.debug("This is debug method");
log.info("This is info method");
log.error("This is error method");

log.log(Level.DEBUG, "This is debug from Level.DEBUG");
log.log(Level.INFO, "This is info from Level.INFO");
log.log(Level.ERROR, "This is error from Level.ERROR");

}
}

4. Compile and run program

If you compile and run from command line, followings are the commands. Make sure to create classes folder inside project for generated class files before executing the commands.


# compile
javac -cp lib/log4j-1.2.17.jar -d classes -sourcepath src src/com/digizol/log4j/helloworld/Main.java

# run
java -cp lib/log4j-1.2.17.jar:./classes:./ com.digizol.log4j.helloworld.Main

If you are using an IDE like Eclipse, you can simply add log4j jar file into the build path before compiling. When running the Main class, you need to give the path to log4j.properties file in run configuration.

5. Check the log messages

In the Main class, we have added two debug level messages. However the rootLogger is configured in INFO level in log4j.properties file, so none of the debug level log messages are expected as outputs.

Console output as as below.

This is info method
This is error method
This is info from Level.INFO
This is error from Level.ERROR

Console has received both INFO and ERROR log messages, but not DEBUG.

However messages.log file has received only the ERROR level log messages as below.

This is error method
This is error from Level.ERROR

This is because the Threshold level of the file logging appender is set to ERROR which overrides the rootLogger configuration.

Hope this helps you to start using log4j in your next project. I have added this project here for your references.

Tuesday, September 17, 2013

Find which process holds a port number in Linux

Here is a simple tip to find out the process that has bounded a given port number. java.net.BindException: Address already in use - this is an error log message that software developers and deployment engineers encounter quite often since the same application or process is already running in the background occupying the port. Below we will locate a process based on the port.

1. Finding the process that holds the port

lsof -i <Internet address>

Let's find the process using the port "8080"

$ lsof -i :8080
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 14124 kamal 35u IPv4 18493 0t0 TCP *:http-alt (LISTEN)

If needed, we can extract just the PID by leaving out all other information as shown below.

$ lsof -i :8080 -t
14124

PID above is the process id that uses the port 8080.

Using this PID, you can view the process details using following command.

ps u -p <PID>

Let's find the process details of PID 14124

$ ps u -p 14124
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
kamal 14124 6.6 7.2 2399340 588220 pts/0 Sl+ 10:39 1:01 /usr/lib/jvm/java-6-sun/bin/java

2. Terminating the process using the process id

A process can be terminated using the kill command.

kill -9 <PID>

Let's kill the above process as follows.

$ kill -9 14124

Hope this helps, also make sure you read details of "lsof" command for further details.

Tuesday, September 10, 2013

[Ubuntu] DeVeDe generated DVD menus not working

DeVeDe is a popular software for DVD creation, and I am using 3.21.0 version of that on Ubuntu 12.04 to generate DVDs from different files of .avi, .mpg and .mp4 types. However after the upgrade to Ubuntu 12.04, I was facing issues with the menus of generated DVD. Recently, I noticed that this is due to an incompatibility issue with ffmpeg solution provided by Ubuntu (detailed bug is found here).

Simplest workaround for this issue is to avoid the use of ffmpeg, and interestingly DeVeDe provides an option to do this.

Go to "Edit -> Preferences"
then uncheck "Use FFMPEG instead of Mencoder" as shown in the below image.

That setting will resolve this problem.

Tuesday, September 3, 2013

[Ubuntu] Troubleshoot USB Pen drives with powerful tools

My USB pen drive was not shown in Ubuntu 12.04 suddenly, so I tried it with Windows, but the result was same. That isolated the issue to the pen drive itself than the operating system. With Ubuntu, I used a lot of powerful tools to resolve this issue, and I am recording those below hoping that will help someone. However please note that there is no guarantee that these tools and instructions are going to resolve the issues you might face with your pen drives.

Steps I followed were:
  1. Check whether your USB device is detected using "lsusb" command
  2. Finding where the device is located (using fdisk)
  3. Guess PC-type hard disk partitions using gpart
  4. Manipulate partitions using gparted (Gnome partition editor)
  5. Scan and repair disk partitions (using testdisk)
  6. Finding bad blocks using badblocks
  7. Copy zeros to starting locations (using dd)

Followings are the details those steps with the commands and the output of each.

1. Check whether your USB device is detected using "lsusb" command

lsusb is a command used to list all USB devices found in a system

$ lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
...
Bus 002 Device 008: ID 0930:6544 Toshiba Corp. Kingston DataTraveler 2.0 Stick (2GB)
...

Above command lists the connected USB devices, and my Kingston DataTraveler 2.0 Stick is also shown. So it is clear that the USB flash drive is correctly connected.

2. Finding where the device is located (using fdisk)

"fdisk" command can be used to find details about the device.

$ sudo fdisk -l
....
Disk /dev/sdc: 8010 MB, 8010194944 bytes
247 heads, 62 sectors/track, 1021 cylinders, total 15644912 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0xd0e2392f

Disk /dev/sdc doesn't contain a valid partition table

So this device size is correctly identified as 8010MB (8GB) and is located at /dev/sdc. Interestingly, fdisk has reported that this device is not having a valid partition table. So something has happened to the partition table and I wanted to fix it with the help of fdisk command as follows.

$ sudo fdisk /dev/sdc
Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabel
Building a new DOS disklabel with disk identifier 0x4c9b7827.
Changes will remain in memory only, until you decide to write them.
After that, of course, the previous content won't be recoverable.

Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite)

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.

Error closing file

As shown above, fdisk has tried to alter the partition table, but failed. So I tried to add a partition as below, which again failed with the same error message.

# sudo fdisk /dev/sdc
...

Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite)

Command (m for help): n
Partition type:
primary (0 primary, 0 extended, 4 free)
extended
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-15644911, default 2048):
Using default value 2048
Last sector, +sectors or +size{K,M,G} (2048-15644911, default 15644911):
Using default value 15644911

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.

Error closing file

So it seemed fdisk can not help further in resolving this issue.

3. Guess PC-type hard disk partitions using gpart

I used gpart to find details of the existing partitions, and following was the outcome.

$ sudo gpart /dev/sdc

Begin scan...
End scan.

Checking partitions...
Ok.

Guessed primary partition table:
Primary partition(1)
type: 000(0x00)(unused)
size: 0mb #s(0) s(0-0)
chs: (0/0/0)-(0/0/0)d (0/0/0)-(0/0/0)r

Primary partition(2)
type: 000(0x00)(unused)
size: 0mb #s(0) s(0-0)
chs: (0/0/0)-(0/0/0)d (0/0/0)-(0/0/0)r

Primary partition(3)
type: 000(0x00)(unused)
size: 0mb #s(0) s(0-0)
chs: (0/0/0)-(0/0/0)d (0/0/0)-(0/0/0)r

Primary partition(4)
type: 000(0x00)(unused)
size: 0mb #s(0) s(0-0)
chs: (0/0/0)-(0/0/0)d (0/0/0)-(0/0/0)r


As per the above findings, there is no correct partition in the device.

4. Manipulate partitions using gparted (Gnome partition editor)


I used "gparted" tool to add a partition table. As shown in above image, gparted shows this device at /dev/sdc with Partition=unallocated and FileSystem=unallocated, so it also identified that there was an issue. So I tried adding a partition table [by Device -> Create Partition Table...] of msdos type, but GUI displayed an error message as "Error while creating partition table". Command line also had some issues listed as below.

$ sudo gparted
======================
libparted : 2.3
======================
/dev/sdc: unrecognised disk label
/dev/sdc: unrecognised disk label
Input/output error during write on /dev/sdc
Error fsyncing/closing /dev/sdc: Input/output error
/dev/sdc: unrecognised disk label

So gparted also failed to resolve this for me.

5. Scan and repair disk partitions (using testdisk)

I tried "testdisk" tool to analyze and repair the disk. Following devices were identified by the tool.

$ sudo testdisk
TestDisk 6.13, Data Recovery Utility, November 2011
....
Select a media (use Arrow keys, then press Enter):
...
Disk /dev/sdc - 8010 MB / 7639 MiB - Kingston DT 101 G2

Partition details of this /dev/sdc were shown as below.

Disk /dev/sdc - 8010 MB / 7639 MiB - CHS 1021 247 62
Current partition structure:
Partition Start End Size in sectors
P Unknown 0 0 1 1021 150 18 15644912

Disk /dev/sdc - 8010 MB / 7639 MiB - CHS 1021 247 62
Partition Start End Size in sectors

No partition found or selected for recovery

As per the above, there is no partitions in this disk.

Also I tried to use this tool to create a new MBR record, and the command resulted as below.

Write a new copy of MBR code, confirm ? (Y/N)
TestDisk exited normally.
You have to reboot for the change to take effect.

However even after reconnecting the device, the issue was not resolved.

6. Finding bad blocks using badblocks

Finally I suspected whether the pen drive was having bad blocks, so tried the badblocks utility to check for those as follows.

$ badblocks -vws /dev/sdc
Checking for bad blocks in read-write mode
From block 0 to 7822455
Testing with pattern 0xaa: 0.03% done, 34:50 elapsed. (0/0/0 errors)

However this tool was taking much longer time to run. As shown above only 0.03 was completely in 34.50 minutes, which means around 80 days to complete. Obviously, I was not going to wait that longer to fix the pen drive.

7. Copy zeros to starting locations (using dd)

I tried "dd" tool to write zeros to the device in case there were some inconsistency in the partition table creation space. So 8MB of zeros were written to pen drive successfully.

$ sudo dd if=/dev/zero of=/dev/sdc bs=8M count=1
1+0 records in
1+0 records out
8388608 bytes (8.4 MB) copied, 2734.83 s, 3.1 kB/s

However even after dd was successful, I tried to add a partition table with gparted as explained in step 4 above, but it continued to fail.

Summary

Finally after all these operations, partition table creation was not successful even though I was able to write some data into this pen drive with 'dd' tool. Hence it is not possible to boot and mount inside an operation system. I assumed this was due to a hardware failure of the device.

Hope these details will help someone (including me) when resolving issues with USB pen drives in future.

Tuesday, August 6, 2013

Thunderbird: Search by Attachment Name

Finding emails which included had a particular attachment is really important. Last week I happened to digg through my email box to find a number of emails that contained a particular document as an attachment. The only information I know about those emails is; those contained this particular attachment. So how can I find the email?

It is quite simple; since the filename is already known, search box on top right-hand side can be used. As shown in the below image, you need to type the filename inside inverted comma.

In this example, I am searching for a file named "Digizol.com Thunderbird Article.doc".

To summarize, three simple steps are;
1. Press 'Ctrl + k'
2. Type filename inside inverted commas
3. Press Enter

Hope this helps.

Wednesday, July 31, 2013

Minimum difference in two sorted arrays

Given two sorted arrays of same length, find pairs of numbers (one from each array) which has the minimum distance between those two numbers. This is the last weeks Thursday Coding Puzzle. Since both arrays are sorted, binary search is going be really useful in searching the values in arrays.
Even though this problem is not related to finding the exact matches as in binary search, it is easy to solve this problem with the same approach used in binary search. As a preparation for this puzzle, it is really useful if you can try and write binary search yourself without referring to internet for help.

This problem can be simplified into two steps and implemented incrementally. Initially, we can simplify this problem to use only one array out of the two; then use one value from the other array rather than the second array itself. Then enhance that solution to use all values in second array against the first array to complete the answer for the problem.

One Array against One Value problem

In this problem, it is required to find a value within the array such that it is the closest to the given value. There can be one of multiple values that are the closest to a given value; so that has to be supported.

Test Cases

As usual, test cases are written first before writing any production code. Followings are the four test cases.

1. shouldReturnEmptyForAnEmptyArray
     > If the array is empty, result has to be empty

2. shouldReturnSameValueIfFoundAnywhereInGivenArray
     > If the given array contains the given value, the distance is zero (0). So it has to be returned from the array other than any value.
     e.g.: For an array with 1, 4, 7, 11 against value 4, then number pair has to be (4,4)

3. shouldReturnCorrectIfOneClosestValueIsAnywhereInGivenArray
     > If the given array contains one closest value, then that is the minimum distance. So it has to be returned with the given value.
     e.g.: For an array with 1, 4, 7, 11 against value 5, then minimum distance is 1 for the number pair (4,5) which has to be returned.

4. shouldReturnCorrectIfMultipleValuesAreTheClosest
     > If the given array contains multiple values closest to the given value, then those has to be returned with the given value.
     e.g.: For an array with 1, 4, 8, 11 against value 6, then minimum distance is 2 for the number pairs (4,6) and (6,8) which has to be returned.

Above test cases are implemented in the following manner with JUnit4.
package com.digizol.puzzle;

import static org.junit.Assert.assertEquals;
import java.util.*;
import org.junit.Test;

public class MinimumDifferencesTest {

private MinimumDifferences sut;

public MinimumDifferencesTest() {
sut = new MinimumDifferences();
}

@Test
public void shouldReturnEmptyForAnEmptyArray() {
assertEquals(0, sut.getMinPair(new int[] {}, 1).length);
}

@Test
public void shouldReturnSameValueIfFoundAnywhereInGivenArray() {
int[] sorted = { 1, 4, 7, 11, 15, 19, 26, 30, 33, 40 };
for (int i = 0; i < sorted.length; i++) {
int[] result = sut.getMinPair(sorted, sorted[i]);
assertEquals(1, result.length);
assertEquals(sorted[i], result[0]);
}
}

@Test
public void shouldReturnCorrectIfOneClosestValueIsAnywhereInGivenArray() {
int[] sorted = { 1, 4, 7, 11, 15, 19, 26, 30, 33, 40 };
int[] result = sut.getMinPair(sorted, sorted[0] - 1);
assertEquals(1, result.length);
assertEquals(sorted[0], result[0]);

for (int i = 0; i < sorted.length; i++) {
result = sut.getMinPair(sorted, sorted[i] + 1);
assertEquals(1, result.length);
assertEquals(sorted[i], result[0]);
}
}

@Test
public void shouldReturnCorrectIfMultipleValuesAreTheClosest() {
int[] sorted = { 1, 4, 7, 11, 15, 19, 26, 30, 33, 40 };
int[] result = sut.getMinPair(sorted, 28);
assertEquals(2, result.length);
List<Integer> expected = new ArrayList<Integer>();
expected.add(26);
expected.add(30);

for (int i = 0; i < result.length; i++) {
expected.remove(Integer.valueOf(result[i]));
}
assertEquals(0, expected.size());
}
}

Production Code

By simply tweaking the binary search code, it is really easy to implement this expected functionality. You can compare the below implementation code with the binary search code; specially look at the three comments shown in both .
package com.digizol.puzzle;

public class MinimumDifferences {

public int[] getMinPair(int[] sorted, int value) {
if (sorted.length == 0) {
return new int[] {};
}
return getMinPair(sorted, value, 0, sorted.length - 1, new int[]{});
}

private int[] getMinPair(int[] sorted, int value,
int leftIndex, int rightIndex, int[] minValues) {

// 1. index check
if (leftIndex > rightIndex) {
return minValues;
}

// 2. middle index
int middleIndex = (leftIndex + rightIndex) / 2;

if (minValues.length == 0) {
minValues = new int[] { sorted[middleIndex] };
} else {
int oldDiff = diff(value, minValues[0]);
int newDiff = diff(value, sorted[middleIndex]);

if (newDiff < oldDiff) {
minValues = new int[] { sorted[middleIndex] };
} else if (newDiff == oldDiff) {
int[] temp = minValues;
minValues = new int[temp.length + 1];
for (int i = 0; i < temp.length; i++) {
minValues[i] = temp[i];
}
minValues[minValues.length - 1] = sorted[middleIndex];
}
}

// 3. recursive invoke
if (sorted[middleIndex] > value) {
return getMinPair(sorted, value, leftIndex, middleIndex - 1, minValues);
} else if (sorted[middleIndex] < value) {
return getMinPair(sorted, value, middleIndex + 1, rightIndex, minValues);
} else {
return minValues;
}
}

private int diff(int value, int currentValue) {

int diff = currentValue - value;
if (diff < 0) {
diff = -diff;
}
return diff;
}
}

Two Arrays Problem

Now we have got the minimum distance number pairs against a given value. Now the enhancement is quite simple, just need to invoke the above "getMinPair(int[] sorted, int value)" method with each value in the second array of the problem and find the smallest minimum of those.

Test Cases

Following is one of the test cases to check this two array based implementation.
    @Test
public void shouldReturnMultiplePairsIfFoundInGivenArrays() {
int[] first = { 1, 10, 20, 30, 40};
int[] second = { 6, 14, 25, 35, 45};
int[][] result = sut.getMinPair(first, second);
assertEquals(2, result.length);

for (int i = 0; i < result.length; i++) {
if (result[i][0] == 6) {
assertEquals(10, result[i][1]);
} else if (result[i][0] == 10) {
if (result[i][1] != 6 && result[i][1] != 14) {
assert false;
}
} else if (result[i][0] == 14) {
assertEquals(10, result[i][1]);
}
}
}
You can insert the following method into the above implemented MinimumDifferences class to complete the implementation for the puzzle.
    public int[][] getMinPair(int[] first, int[] second) {
int[][] pairs = new int[0][];

int diff = Integer.MAX_VALUE;

for (int i = 0; i < second.length; i++) {

// invoke modified binary search method
int[] mins = getMinPair(first, second[i]);

if (mins.length != 0) {
int localDiff = mins[0] - second[i];
if (localDiff < 0) {
localDiff = -localDiff;
}
if (diff > localDiff) {
diff = localDiff;
pairs = new int[mins.length][2];
for (int j = 0; j < mins.length; j++) {
int[] value = new int[]{mins[j], second[i]};
pairs[j] = value;
}
} else if (diff == localDiff) {
int[][] temp = pairs;
pairs = new int[temp.length + mins.length][2];
for (int j = 0; j < temp.length; j++) {
pairs[j] = temp[j];
}
for (int j = 0; j < mins.length; j++) {
int[] value = new int[]{mins[j], second[i]};
pairs[j + temp.length] = value;
}
}
}
}
return pairs;
}
Hope this helps you to understand how binary search can be modified to solve two sorted arrays based problem.

Related Articles

Java: Binary Search (recursive) & TestCases

Test cases for Binary search might not be something you have already written, but the implementation must be an old exercise you may have done in your algorithm lessons. May be it is easy for you to write it yourself without referring to examples or helping materials? I think it's time for you to try it yourself if you have not done it for a long time.

Since I wanted to solve a puzzle with binary search, I decided to write binary search myself. If you can not remember what the binary search is; a given value must be searched in a sorted array with the aim of minimizing the number of operations by limiting the search into the left or right half of the array by dividing it into two parts.

Test Cases

Test cases for this is not that specific to binary search, but mostly for any search. However as this search is executed in half by half approach, I wrote a number of test cases to search for the values in first, last, middle indexes followed by an all index search. Also since the array division is changing based on whether array length is odd or even, two test cases are added for that.

Here are the names of the test cases.
  1. shouldReturnFalseIfArrayIsEmpty()
  2. shouldReturnFalseIfNotFoundInSortedOddArray()
  3. shouldReturnFalseIfNotFoundInSortedEvenArray()
  4. shouldReturnTrueIfFoundAsFirstInSortedArray()
  5. shouldReturnTrueIfFoundAtEndInSortedArray()
  6. shouldReturnTrueIfFoundInMiddleInSortedArray()
  7. shouldReturnTrueIfFoundAnywhereInSortedArray()
  8. shouldReturnFalseIfNotFoundInSortedArray()

Above names are a bit self-explanatory, please see the following code for details.
package com.digizol.algorithms;

import static org.junit.Assert.*;
import org.junit.*;

public class BinarySearchTest {

private BinarySearch sut;

@Before
public void setUp() throws Exception {
sut = new BinarySearch();
}

@Test
public void shouldReturnFalseIfArrayIsEmpty() {
assertEquals(false, sut.find(new int[] {}, 1));
}

@Test
public void shouldReturnFalseIfNotFoundInSortedOddArray() {
assertEquals(false,
sut.find(new int[] { 0, 2, 4, 6, 8, 10, 12, 14, 16 }, 9));
}

@Test
public void shouldReturnFalseIfNotFoundInSortedEvenArray() {
assertEquals(false,
sut.find(new int[] { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18 }, 9));
}

@Test
public void shouldReturnTrueIfFoundAsFirstInSortedArray() {
assertEquals(true,
sut.find(new int[] { 0, 2, 4, 6, 8, 10, 12, 14, 16 }, 0));
}

@Test
public void shouldReturnTrueIfFoundAtEndInSortedArray() {
assertEquals(true,
sut.find(new int[] { 0, 2, 4, 6, 8, 10, 12, 14, 16 }, 16));
}

@Test
public void shouldReturnTrueIfFoundInMiddleInSortedArray() {
assertEquals(true,
sut.find(new int[] { 0, 2, 4, 6, 8, 10, 12, 14, 16 }, 8));
}

// covers the 'true' cases above
@Test
public void shouldReturnTrueIfFoundAnywhereInSortedArray() {
int[] sorted = new int[] { 0, 2, 4, 6, 8, 10, 12, 14, 16 };

for (int i = 0; i < sorted.length; i++) {
assertEquals(true, sut.find(sorted, sorted[i]));
}
}

// covers the 'false' cases above
@Test
public void shouldReturnFalseIfNotFoundInSortedArray() {
int[] sorted = new int[] { 0, 2, 4, 6, 8, 10, 12, 14, 16 };

assertEquals(false, sut.find(sorted, sorted[0] - 1));
for (int i = 0; i < sorted.length; i++) {
assertEquals(false, sut.find(sorted, sorted[i] + 1));
}
}
}

Production Code

I want to stress the importance of you trying yourself to complete the code yourself rather than directly going to the code below.

I wrote below recursion based production code which passes against above test cases. There are three comments in the code, which helps you to remember the logic easily.
package com.digizol.algorithms;

public class BinarySearch {

public boolean find(int[] sortedValues, int value) {
return search(sortedValues, value, 0, sortedValues.length - 1);
}

private boolean search(int[] sorted, int value, int leftIndex, int rightIndex) {

// 1. index check
if (leftIndex > rightIndex) {
return false;
}

// 2. middle index
int middle = (rightIndex + leftIndex) / 2;

// 3. recursive invoke
if (sorted[middle] > value) {
return search(sorted, value, leftIndex, middle - 1);
} else if (sorted[middle] < value) {
return search(sorted, value, middle + 1, rightIndex);
} else {
return true;
}
}

}
If you reached here after writing the program yourself, you deserve a round of applause. Congratulation!!!

Related Articles