Tutorial – How to create a simple Firefox plugin from scratch in 10 minutes

December 4th, 2009 Karthikeyan C 2 comments

In this post we will create a Firefox plugin from scratch in 10 minutes. Navigate to any folder of your choice and we will call this as ROOT folder for the plugin.

  • Create an empty folder called chrome under ROOT folder
  • Create two empty files called install.rdf and chrome.manifest under ROOT folder.

Now let us decide what we want to do with the plugin. The plugin will contain links to various social networking sites like Twitter, Orkut (we limit to 2 as it is just an example).

  • Now under chrome folder  create two empty folders called content and skin. The below screen shot shows the folder structure so far.

firefoxpluginfolders

Explanation for the folders/files created so far:

skin will contain the images and css files used in the plugin (if any). content folder will contain Javascript , XUL files involved in the plugin. chrome.manifest is self explanative and provides the information about the skin, overlay, content location to Firefox. install.rdf contains the information like plugin creator, minimum and maximum compatible versions of Firefox for the plugin.

Let us create a file called social.xul under content folder with the below lines of code.

<?xml version="1.0"?>
<overlay id="social_karthikeyanc_com"
 xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:html="http://www.w3.org/1999/xhtml" orient="vertical">

 <script type="application/x-javascript"
 src="chrome://social/content/social.js" />
<toolbox id="navigator-toolbox">
<toolbar id="Social-Toolbar" toolbarname="Social Toolbar" accesskey="H"
 context="toolbar-context-menu"
 hidden="false" persist="hidden">
<toolbarbutton id="Orkut-Button" tooltiptext="Orkut Home"
 label="Go To Orkut" oncommand="loadURL('http://www.orkut.com')"/>
<toolbarseparator />
<toolbarbutton id="Twitter-Button" tooltiptext="Twitter Home"
 label="Go To Twitter" oncommand="loadURL('http://www.twitter.com')"/>

</toolbar>
</toolbox>
</overlay>

Now create a file called social.js under content folder with the below code.


function loadURL(url)
{
 // Set the browser window's location to the incoming URL
 window._content.document.location = url;
 // Make sure that we get the focus
 window.content.focus();
}

Please open chrome.manifest empty file with a text editor and paste the lines below.


content social jar:chrome/social.jar!/content/
overlay chrome://browser/content/browser.xul chrome://social/content/social.xul
skin social classic/1.0 jar:chrome/social.jar!/skin/

Open install.rdf and paste the lines below.


<?xml version="1.0"?>
<RDF:RDF xmlns:em="http://www.mozilla.org/2004/em-rdf#"
 xmlns:NC="http://home.netscape.com/NC-rdf#"
 xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#">

 <Description about="urn:mozilla:install-manifest">
 <em:id>contact@yourwebsitename.com</em:id>
 <em:version>1.0</em:version>
 <em:type>2</em:type>

 <!-- Target Application this extension can install into,
 with minimum and maximum supported versions. -->
 <em:targetApplication>
 <Description>
 <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
 <em:minVersion>2.0</em:minVersion>
 <em:maxVersion>3.5.*</em:maxVersion>
 </Description>
 </em:targetApplication>

 <!-- Front End MetaData -->
 <em:name>www.Karthikeyanc.com</em:name>
 <em:description>Karthikeyan C's Developer Blog</em:description>
 <em:creator>Karthikeyan Chockalingam</em:creator>
 <em:homepageURL>http://www.karthikeyanc.com/</em:homepageURL>
 </Description>
</RDF>

Now navigate to chrome folder and execute the below command. (I am using Ubuntu. Same can be achieved in other OS like windows using a zip utility like 7-zip)


zip -r social.jar content/* skin/*

Now navigate one step up to ROOT folder and execute the below command to create your Firefox plugin social.xpi. You can install the plugin by choosing File –Open File in Firefox menu.


zip social.xpi install.rdf chrome.manifest chrome/social.jar
  • Share/Bookmark

Wordpress tricks useful for me

December 3rd, 2009 Karthikeyan C No comments

This link by perishablepress.com is rather a long post which is very useful and I badly needed the below trick as the wordpress database size was growing too fast.

- Disabling post revisions by adding the following line to wp-config.php

define('WP_POST_REVISIONS', FALSE);

-

  • Share/Bookmark

How to improve performance of Seam based RichFaces JSF application

December 2nd, 2009 Karthikeyan C 3 comments

I was trying to improve the performance (decrease the time taken to render the pages)   of a Seam based JSF application (Infact this post is applicable to any web application using RichFaces).

Initially the response time for JSF pages was around 12 to 20 seconds (The internet connection speed was roughly 512kbps). I tried the optimisation techniques mentioned in the links in this post http://www.karthikeyanc.com/blog/index.php/2009/11/jsf-and-richfaces-optimization-links/

Even then the page rendering time did not decrease substantially. So started using Firefox with YSlow and HttpFox add-ons.

Found that the js, css and image files related to RichFaces were expiring immediately and hence each time a JSF page was rendered, the resources (js,css and image files) were not fetched from local cache and the request was sent to the server again (It does not matter even if it is 304 Unmodified as already the damage is done and increases the response time).

Hence wrote a Servlet Filter which will override the default time to expire (which is immediate) and add a configurable duration as the time to expire. Part of the Filter code is provided below. The Filter name is ResponseHeaderFilter.java


public void init(FilterConfig filterConfig) {
 this.filterConfig = filterConfig;
 }

@Override
 public void doFilter(ServletRequest request, ServletResponse response,
 FilterChain chain)
 throws IOException, ServletException {

 HttpServletResponse httpResp = (HttpServletResponse) response;
 Enumeration e = filterConfig.getInitParameterNames();
 while (e.hasMoreElements()) {
 String headerName = (String) e.nextElement();
 httpResp.addHeader(headerName, filterConfig.getInitParameter(headerName));
 }
 chain.doFilter(request, response);
 }

In web.xml I added the following configuration for the filter.


<filter>
 <filter-name>CacheForDuration</filter-name>
 <filter-class>com.packagename.ResponseHeaderFilter</filter-class>
 <init-param>
 <param-name>Cache-Control</param-name>
 <param-value>max-age=900000, public</param-value>
 </init-param>
 </filter>

<filter-mapping>
 <filter-name>CacheForDuration</filter-name>
 <url-pattern>/img/*</url-pattern>
 </filter-mapping>
 <filter-mapping>
 <filter-name>CacheForDuration</filter-name>
 <url-pattern>/js/*</url-pattern>
 </filter-mapping>
 <filter-mapping>
 <filter-name>CacheForDuration</filter-name>
 <url-pattern>/css/*</url-pattern>
 </filter-mapping>
 <filter-mapping>
 <filter-name>CacheForDuration</filter-name>
 <url-pattern>/scripts/*</url-pattern>
 </filter-mapping>
 <filter-mapping>
 <filter-name>CacheForDuration</filter-name>
 <url-pattern>/a4j/*</url-pattern>
 </filter-mapping>

Once this configuration was in place the resources (js, css and scripts) were fetched from local cache of the browser and hence the response time was reduced to 2 to 3 seconds. Hope this is useful.

  • Share/Bookmark
Categories: Development Tags: ,

Redirecting permanently in HttpServlet from your old domain (website) to new domain

November 29th, 2009 Karthikeyan C No comments

Let us assume we face a scenario where we move from a old domain (website) to a new domain (website). You may do this when you expand your business offering and the old name may not be appropriate.

But your old domain has gained reputation (like a good page rank and a number of incoming links) which you wish to carry forward to your new domain. One way of doing this is respond with HTTP code 301 which is permanently moved.

You may also make use of use Google web master tools to inform the change in domain address (as Google is currently the #1 search engine ). This will prevent the decrease in hits to your website from search engines.

The below code shows how to implement it if you host a Java web application for your old domain.

In web.xml make the below entry.


<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
 <servlet>
 <servlet-name>RedirectionServlet</servlet-name>
 <servlet-class>com.olddomain.web.servlet.RedirectionServlet</servlet-class>
 </servlet>
 <servlet-mapping>
 <servlet-name>RedirectionServlet</servlet-name>
 <url-pattern>/*</url-pattern>
 </servlet-mapping>
 </web-app>

Next the code for RedirectionServlet.java


package com.olddomain.web.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class RedirectionServlet extends HttpServlet {

 protected void processRequest(HttpServletRequest request, HttpServletResponse response)
 throws ServletException, IOException {

 //Get the incoming URL request.
 response.setHeader("Location", "http://www.yournewdomain.com"+request.getRequestURI());
 response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
 }

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

 @Override
 protected void doPost(HttpServletRequest request, HttpServletResponse response)
 throws ServletException, IOException {
 processRequest(request, response);
 }
}

Note: Using response.sendRedirect will produce only HTTP status code 302 which is temporarily moved and not 301 which indicates it is permanently moved.

  • Share/Bookmark

Check your website’s Domain Name Server (DNS) propagation

November 28th, 2009 Karthikeyan C No comments

When we change our website’s hosting provider from ProviderA to ProviderB we need to change the domain name servers with the domain registration account (like GoDaddy). This may take anywhere from few minutes to 72 hours. To check if the DNS information update has happened, I found the below links very helpful.

http://www.preshweb.co.uk/cgi-bin/dns-propagation-tracker.pl

http://www.whatsmydns.net/

  • Share/Bookmark
Categories: Tools / Utilities Tags:

MySQL database schema browser and SQL executor in Ubuntu 9.10

November 26th, 2009 Karthikeyan C 1 comment

To install MySQL database schema browser,  SQL executor and administrator, use the following command. It gives a cool GUI for  us to work with.


sudo apt-get install mysql-query-browser mysql-admin
  • Share/Bookmark

PrimeFaces File Upload component hack

November 25th, 2009 Karthikeyan C No comments

If PrimeFaces file upload does not work, mostly the reason will be that the prependId attribute was not set to false in the h:form. After the user browses the file nothing happens and we are left wondering as there is no JavaScript error.

I have configured the PrimeFaces file upload as below in one of my UI page.


<h:form id="myform" enctype="multipart/form-data" prependId="false">
 <p:fileUpload fileUploadListener="#{userprofile.handleFileUpload}"
 allowTypes="*.jpg;*.png;*.gif;" description="User Profile Image"/>

 </h:form>
  • Share/Bookmark
Categories: Development Tags:

When to use ajaxSingle=”true” in a4j (AJAX for JavaServer Faces)

November 25th, 2009 Karthikeyan C No comments

Let us consider a scenario where we can use the attribute ajaxSingle in a JSF  and Seam based application.

We have a country drop down and a dependent state drop down in a given UI. Both country and state are mandatory fields. As you can see from the code below, I am using Seam validation by mentioning s:validateAll.


<h:form>
<s:validateAll>
 <h:panelGrid columns="3">
 <h:outputLabel for="country">Select Country:</h:outputLabel>

 <h:selectOneMenu  id="country"  value="#{searchaction.country}" required="true">
 <s:selectItems value="#{countries}" var="cntry" label="#{cntry.name}"
 noSelectionLabel="select..." />
 <s:convertEntity />
 <a:support  action="#{searchaction.handleCountrySelection}" reRender="state" event="onchange">
 <a:ajaxListener type="org.ajax4jsf.ajax.ForceRender"/>
 </a:support>

 </h:selectOneMenu>
 <rich:message for="country"/>

 <h:outputLabel for="state">Select State:</h:outputLabel>

 <h:selectManyListbox  size="#{searchaction.states.size+1}" id="state"  value="#{searchaction.state}" required="true">
 <s:selectItems value="#{searchaction.states}" var="state" label="#{state.name}"
 />
 <s:convertEntity />

 </h:selectManyListbox>
<rich:message for="state"/>
</h:panelGrid>
</s:validateAll>
</h:form>

As I have assigned true to required attribute of state selectManyListbox, when user changes the selection in country drop down, we get a validation error message saying that state field is required. This is because during the AJAX submission the entire form details is submitted and hence validationhappens on all fields.

So as a solution, we assign the attribute ajaxSingle to the AJAX submission of  country drop down as below. This validates only country drop down and enables the population of the state drop down.


<a:support  action="#{searchaction.handleCountrySelection}" reRender="state" event="onchange" ajaxSingle="true">
 <a:ajaxListener type="org.ajax4jsf.ajax.ForceRender"/>
 </a:support>
  • Share/Bookmark
Categories: Development Tags: , ,

Configuring user role based navigation from error page in Seam framework

November 24th, 2009 Karthikeyan C No comments

Let us assume a scenario where multiple roles exist for users. But we wish to display a single error page and from this error page they should click a button (or link) and go to their respective home page.

This can be achieved by using the following code snippet which is in error.xhtml


<h:form id="errorform">
 <h3> <rich:messages errorClass="error" level="warn"/></h3>

 <h:commandLink  action="/role1/main1.xhtml" rendered="#{s:hasRole('role1')}">
 <h3>Click Here To Proceed </h3>
 </h:commandLink>
 <h:commandLink  action="/role2/main2.xhtml" rendered="#{s:hasRole('role2')}">
 <h3>Click Here To Proceed </h3>
 </h:commandLink>
 </h:form>

We will configure the redirection in pages.xml as below.


<exception class= "java.lang.RuntimeException">
 <redirect view-id="/error.xhtml">
 <message severity="warn">Cannot perform the requested operation due to error. </message>
 </redirect>
 </exception>
  • Share/Bookmark
Categories: Development Tags:

Configuring OsTicket for your website in shared server hosting

November 24th, 2009 Karthikeyan C No comments

Many of the shared server hosting providers do not enable email piping. Hence OsTicket may not work resulting in an error “local delivery failed”.

But they may provide an option to use IMAP/POP poll to retrieve the ticket information (This should be enabled in the Email related settings in OsTicket). Now to enable this poll we have to setup a cronjob. Before setting up cronjob, we can know the PHP location by running the following command.

which php

which will produce a result like

/usr/local/bin/php

.

Now set up a cronjob with the following command.

/usr/local/bin/php  /home/username/pathToOsTicketInstallation/api/cron.php

Note: Please ensure cron.php has executable rights (else run chmod +x)

  • Share/Bookmark