Saturday, October 27, 2012

How to place the Facebook "Like Box" to your web site or Blog?

One of the very useful social plugin provided by the Facebook is 'Like Box'. If you have placed Facebook like box in your website or blog, then your visitors can make 'likes' to it. This will not be a partial tutorial. I don't want to leave any thing unclear about this. At the end of this tutorial, you must be able to add Facebook like box into your website or blog.

Just look at the right side bar of my blog. You can see Facebook like box there. Unfortunately by this time, my wife and my self has liked to my Blog. I hope, you will also like my blog after reading this tutorial.

OK, let's move to real topic!

Go to this URL,

http://developers.facebook.com/docs/plugins/


There you can see all the plugins available with Facebook. Just scroll down and you can see 'Like Box' plugin for you. Click on that link and you will get the following form.


I guess, most of the fields of the right side form are clear for you. But the first field which is 'Facebook Page URL', confuses us. Some people think, this should be your blog or website URL and some are thinking, this should be a Facebook's application URL. So they create new Facebook application and try to get the Facebook like box. Actually as it says, it should be the Facebook page URL. You have to create a Facebook page so that your website or blog will get likes via that page. Facebook 'Like Box' is the plugin which connects Facebook page with our website or blog. We don't actually want visitors to visit Facebook page, but we want, visitors should visit our website or blog. The ultimate target is, we want to allow our visitors of blog or website to give their impression on it by giving a 'likes'.

As the first step, let,s create Facebook page first. Login to your Facebook account and click on 'Like Pages' link on left side bar under PAGES category of Facebook home page. You will get the following page.



You can see 'Create a Page' green color button on right top area of the page. Click on that and you will get the following page.


You can see several categories on this page. Select the one appropriate for you and provide the required details. It is important to provide unique name for your page, because visitors will see that on website or blog. I selected 'Company, Organization or Institution' and my page name is 'Lasanthiblog'. You can see it from bellow image.


After providing a good name for your page, proceed by clicking on 'Get Started' button. You will get the following page which is very important.

As you can see from this image, we have to complete four steps to create our Facebook page. As the first step upload a picture for your Facebook page profile and click 'Save Photo' button. You will be directed to second step. See the picture bellow.


You have to provide some description about your page and URL of your website or blog. I have provided my blog's URL as you can see. Go to next step by clicking on 'Save Info' button. Next page will be displayed as follows.


This step is very important. You will get the public URL of your page from here. You can select proper and meaningful name for your page URL. As you can see, I have given 'lasanthiblog' as page address. Click on 'Set Address' button and you can skip the next step if you don't want to enable adds.

After completing the 4th step, you will be redirected to your page. My page is shown bellow. Actually this is not my real page, I created this page to demonstrate, how to create a Facebook page for you.



Now the hard part is done and you are ready to get Facebook like plugin for your website or blog. Now we have Facebook page RUL.

http://www.facebook.com/lasanthiblog

Now the time to get code for our Facebook like box plugin. Again go to the Facebook plugin page.

http://developers.facebook.com/docs/plugins/

Select 'Like Box' and fill the form. After filling the form click on 'Get Code' button. You can get the code in four different ways. But I suggest you to get 'IFRAME' code.

Now you place this code in your website or blog, where you want to place Facebook like plugin. I guess, you can manage that by your selves. I hope this will be helpful for you and if you are still having problem of getting Facebook 'Like Box', please mail to me. I will help you. OK!, go ahead.

You may also like:

Friday, October 26, 2012

[ERROR] error: error reading *.jar; invalid LOC header (bad signature) - Maven build error

Some time you will get the following error when building a project with maven. Most of the time, this happens after checking out new maven project and try to build the project with an existing repository. Some existing jar files can not be read when building the new project. This may happen because, you may already have some projects sharing the same repository.

The following shows a sample error.

[ERROR] error: error reading /home/vinesh/.m2/repository/org/codehaus/woodstox/stax2-api/3.1.1/stax2-api-3.1.1.jar; invalid LOC header (bad signature)

As a solution for this, you can remove the existing jar file and build the project again in online mode. You can use the following command.

mvn clean install -Dmaven.test.skip=true

Now, carefully look into the console.You can see, it downloads the removed jar file from the maven repository.
You may also like:

Sunday, October 21, 2012

Make your all AJAX request through a single gateway.

AJAX has become a most popular and widely used technology in modern web application. In some web application, around 95% of the server requests are AJAX requests. When you are developing your application, it is always a good practice finding more generic and reusable ways of implementing things. Sometime, we may call as inventing new patterns. 

This tutorial explains a pattern of making your all AJAX requests through a single gateway. I am not explaining a technology feature, but this is programing technique. 

What are the advantages?

  • Suppose you want to pass some common set of parameters with every AJAX request. This can be easily achieved by this technique. 
  • If your application has an exception flow mechanism which brings exception messages happened in your DAO layer or service layer or even in the controller layer into the client view, those can be easily handled in central point with this technique. 
  • If you want to show each operations status to the user, that can also be handled from a central point.
There may be more advantages.I will give you a sample implementation with jQuery. But this can be implemented with any Javascript library as you wish.

If you use jQuery, the following is the typical Javascript method using for AJAX request.

$.ajax({
        type: 'POST',
        url: CONTEXT_ROOT + "/changePassword.htm",
        data: $.blimp.serializeForm("frmChangePwd"),
        success: function (response) {
            //handle success
        },
        error: function () {
            //handle errors
        },
        dataType: 'json'
});


For my application, I have written a common central method to make every AJAX requests. This method works as a gateway which all AJAX requests are passing through this method. Any common functionality that we need to add before making the request as well as after making the request, can easily be added to this common method. The following code shows the common gateway method.


/**
 * @author Semika siriwardana
 * 
 */
(function($) {
     $.myObj = {
  /**
   * Central AJAX caller gateway.
   */
 ajax: function(objConfig) {
   
     $.ajax({
     type: objConfig.type, //mandatory field
     url: objConfig.url, //mandatory
     headers: (objConfig.headers != undefined)?objConfig.headers:{}, 
     async: (objConfig.async != undefined)?objConfig.async:true,
     data : (objConfig.data != undefined)?objConfig.data:{},
     dataType : (objConfig.dataType != undefined)?objConfig.dataType:'json',
     cache: (objConfig.cache != undefined)?objConfig.cache:true,
     contentType: (objConfig.contentType != undefined)?objConfig.contentType:'application/x-www-form-urlencoded',
       
           success: function(data) {
               //Handle success status and do more
               objConfig.success(data); //Invoke success callback method.   
           },
             
           error: function(data, textStatus, jqXHR) {
                       //Handle error status and do more
                objConfig.error(data, textStatus, jqXHR)   
           }
     });
 }
     }
}(jQuery));

As I mentioned before, this is a programing technique or a pattern. You know that '$.ajax()' is the method provided by jQuery for AJAX request. As you see above, I have written a wrapper method as '$.myObj.ajax(objConfig)'. Now onwords, when you want to make any AJAX requests, you are not directly invoking original '$.ajax()' method, but you invoke the wrapper method '$.myObj.ajax(objConfig)'. 

Next, you will have a problem. What is this 'objConfig' parameter passing into '$.myObj.ajax()' method?. You will get the answer soon.
To make your AJAX request through our gateway method, you just need to change '$.ajax' to '$.myObj.ajax' from the above code.

myObj.ajax({
       type: 'POST',
       url: CONTEXT_ROOT + "/changePassword.htm",
       data: $.blimp.serializeForm("frmChangePwd"),
       success: function (response) {
            //handle success
       },
       error: function () {
            //handle errors
       },
       dataType: 'json'
});

If you use '$.myObj.ajax' for your all AJAX requests, you can easily handle some common behaviours with AJAX invocation.

You may also like:

Monday, October 15, 2012

Facebook similar chat for your Java web application.

Chatting is easy just like eating a piece of cake or drinking a hot coffee. Have you ever thought about developing a chat program by yourself?. You know that, it is not easy as chatting. But, if you are a developer and if you read to the end of this article, you may put a try to develop a chatting application by your self and allow your users to chat via your web application. 

I had to implement a chatting application for my web application. As every one does, I started to search on internet. I found IRC. When I read and search more about IRC, I understood that finding a web base client for IRC was difficult. I wanted to have more customizable web client which is working similar to Facebook. At last and luckily, I found CometD. 

Finally, I was able to implement chatting application by using CometD and more customizable chat windows opening on the browser which is exactly similar to Facebook. This works almost all the modern browsers. This article explains step by step, How to implement chatting application from the scratch and also How to integrate chatting application to your existing Java base web application. Remember, Your web application should be a Java base one.

You need to download the cometD from their official web site. It has all the dependencies required to implement the chatting application except tow java script libraries. I have written two Javascript libraries, one to create dynamic chat windows like Facebook and other to handle CometD chatting functionality in generic way. If you can manage these stuff by your self, you don't need to use those tow Javascript libraries. Actually, CometD documentation provides good details. But, I go ahead with the tutorial by using those tow libraries. Any way, I recommend first use those tow libraries and then customize it as you need. I hope to share the sample application with you and you can deploy it in your localhost and test, how it works.

1.Adding required jar files. 

If you use maven to build your project, add the following dependencies into your pom.xml file

<dependencies>
    <dependency>
        <groupId>org.cometd.java</groupId>
        <artifactId>bayeux-api</artifactId>
        <version>2.5.0</version>
    </dependency>
    <dependency>
         <groupId>org.cometd.java</groupId>
         <artifactId>cometd-java-server</artifactId>
         <version>2.5.0</version>
    </dependency>
    <dependency>
         <groupId>org.cometd.java</groupId>
         <artifactId>cometd-websocket-jetty</artifactId>
         <version>2.5.0</version>
         <exclusions>
             <exclusion>
                 <groupId>org.cometd.java</groupId>
                 <artifactId>cometd-java-client</artifactId>
             </exclusion>
         </exclusions>
   </dependency>
   <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-simple</artifactId>
        <version>1.6.6</version>
   </dependency>
   <dependency>
        <groupId>org.cometd.java</groupId>
        <artifactId>cometd-java-annotations</artifactId>
        <version>2.5.0</version>
   </dependency>
</dependencies>

If you are not using maven to build your project, just copy the following .jar files into /WEB-INF/lib folder from your CometD download bundle. You can find these .jar files from /cometd-demo/target/cometd-demo-2.5.0.war file.

  • bayeux-api-2.5.0.jar
  • cometd-java-annotations-2.5.0.jar
  • cometd-java-common-2.5.0.jar
  • cometd-java-server-2.5.0.jar
  • cometd-websocket-jetty-2.5.0.jar
  • javax.inject-1.jar
  • jetty-continuation-7.6.7.v20120910.jar
  • jetty-http-7.6.7.v20120910.jar
  • jetty-io-7.6.7.v20120910.jar
  • jetty-jmx-7.6.7.v20120910.jar
  • jetty-util-7.6.7.v20120910.jar
  • jetty-websocket-7.6.7.v20120910.jar
  • jsr250-api-1.0.jar
  • slf4j-api-1.6.6.jar
  • slf4j-simple-1.6.6.jar

2.Adding required Javascript files.

You need to link the following Javascript files.

  • cometd.js
  • AckExtension.js
  • ReloadExtension.js
  • jquery-1.8.2.js
  • jquery.cookie.js
  • jquery.cometd.js
  • jquery.cometd-reload.js
  • chat.window.js
  • comet.chat.js
The 'chat.window.js' and 'comet.chat.js' are my own tow Javascript libraries which does not come with CometD distribution. If you are totally following this tutorial, you have to link those tow libraries as well. Provided sample application has these tow Javascript libraries. 

3.Writing chat service class.

/**
 * @author Semika siriwardana
 * CometD chat service.
 */
package com.semika.cometd;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import javax.inject.Inject;

import org.cometd.annotation.Configure;
import org.cometd.annotation.Listener;
import org.cometd.annotation.Service;
import org.cometd.annotation.Session;
import org.cometd.bayeux.client.ClientSessionChannel;
import org.cometd.bayeux.server.BayeuxServer;
import org.cometd.bayeux.server.ConfigurableServerChannel;
import org.cometd.bayeux.server.ServerMessage;
import org.cometd.bayeux.server.ServerSession;
import org.cometd.server.authorizer.GrantAuthorizer;
import org.cometd.server.filter.DataFilter;
import org.cometd.server.filter.DataFilterMessageListener;
import org.cometd.server.filter.JSONDataFilter;
import org.cometd.server.filter.NoMarkupFilter;

@Service("chat")
public class ChatService {
    private final ConcurrentMap<String, Map<String, String>> _members = new ConcurrentHashMap<String, Map<String, String>>();
    @Inject
    private BayeuxServer _bayeux;
    @Session
    private ServerSession _session;

    @Configure ({"/chat/**","/members/**"})
    protected void configureChatStarStar(ConfigurableServerChannel channel) {
        DataFilterMessageListener noMarkup = new DataFilterMessageListener(new NoMarkupFilter(),new BadWordFilter());
        channel.addListener(noMarkup);
        channel.addAuthorizer(GrantAuthorizer.GRANT_ALL);
    }

    @Configure ("/service/members")
    protected void configureMembers(ConfigurableServerChannel channel) {
        channel.addAuthorizer(GrantAuthorizer.GRANT_PUBLISH);
        channel.setPersistent(true);
    }

    @Listener("/service/members")
    public void handleMembership(ServerSession client, ServerMessage message) {
        Map<String, Object> data = message.getDataAsMap();
        final String room = ((String)data.get("room")).substring("/chat/".length());
        
        Map<String, String> roomMembers = _members.get(room);
        if (roomMembers == null) {
            Map<String, String> new_room = new ConcurrentHashMap<String, String>();
            roomMembers = _members.putIfAbsent(room, new_room);
            if (roomMembers == null) roomMembers = new_room;
        }
        final Map<String, String> members = roomMembers;
        String userName = (String)data.get("user");
        members.put(userName, client.getId());
        client.addListener(new ServerSession.RemoveListener() {
            public void removed(ServerSession session, boolean timeout) {
                members.values().remove(session.getId());
                broadcastMembers(room, members.keySet());
            }
        });

        broadcastMembers(room, members.keySet());
    }

    private void broadcastMembers(String room, Set<String> members) {
        // Broadcast the new members list
        ClientSessionChannel channel = _session.getLocalSession().getChannel("/members/"+room);
        channel.publish(members);
    }

    @Configure ("/service/privatechat")
    protected void configurePrivateChat(ConfigurableServerChannel channel) {
        DataFilterMessageListener noMarkup = new DataFilterMessageListener(new NoMarkupFilter(),new BadWordFilter());
        channel.setPersistent(true);
        channel.addListener(noMarkup);
        channel.addAuthorizer(GrantAuthorizer.GRANT_PUBLISH);
    }

    @Listener("/service/privatechat")
    protected void privateChat(ServerSession client, ServerMessage message) {
        Map<String,Object> data = message.getDataAsMap();
        
        String room = ((String)data.get("room")).substring("/chat/".length());
        Map<String, String> membersMap = _members.get(room);
        if (membersMap == null) {
            Map<String,String>new_room=new ConcurrentHashMap<String, String>();
            membersMap=_members.putIfAbsent(room,new_room);
            if (membersMap==null)
                membersMap=new_room;
        }
        
        String peerName = (String)data.get("peer");
        String peerId = membersMap.get(peerName);
        
        if (peerId != null) {
            
         ServerSession peer = _bayeux.getSession(peerId);
            
            if (peer != null) {
             Map<String, Object> chat = new HashMap<String, Object>();
                String text = (String)data.get("chat");
                chat.put("chat", text);
                chat.put("user", data.get("user"));
                chat.put("scope", "private");
                chat.put("peer", peerName);
                ServerMessage.Mutable forward = _bayeux.newMessage();
                forward.setChannel("/chat/" + room);
                forward.setId(message.getId());
                forward.setData(chat);

                if (text.lastIndexOf("lazy") > 0) {
                    forward.setLazy(true);
                }
                if (peer != client) {
                    peer.deliver(_session, forward);
                }
                client.deliver(_session, forward);
            }
        }
    }

    class BadWordFilter extends JSONDataFilter {
        @Override
        protected Object filterString(String string) {
            if (string.indexOf("dang") >= 0) {
                throw new DataFilter.Abort();
            }
            return string;
        }
    }
}

4.Changing web.xml file.

You should add the following filter into your web.xml file.

<filter>
     <filter-name>continuation</filter-name>
     <filter-class>org.eclipse.jetty.continuation.ContinuationFilter</filter-class>
</filter>
<filter-mapping>
     <filter-name>continuation</filter-name>
     <url-pattern>/cometd/*</url-pattern>
</filter-mapping>

And also the following servlet.

<servlet>
    <servlet-name>cometd</servlet-name>
    <servlet-class>org.cometd.annotation.AnnotationCometdServlet</servlet-class>
    <init-param>
         <param-name>timeout</param-name>
         <param-value>20000</param-value>
    </init-param>
    <init-param>
         <param-name>interval</param-name>
         <param-value>0</param-value>
    </init-param>
    <init-param>
         <param-name>maxInterval</param-name>
         <param-value>10000</param-value>
    </init-param>
    <init-param>
         <param-name>maxLazyTimeout</param-name>
         <param-value>5000</param-value>
    </init-param>
    <init-param>
         <param-name>long-polling.multiSessionInterval</param-name>
         <param-value>2000</param-value>
    </init-param>
    <init-param>
         <param-name>logLevel</param-name>
         <param-value>0</param-value>
    </init-param>
    <init-param>
         <param-name>transports</param-name>
         <param-value>org.cometd.websocket.server.WebSocketTransport</param-value>
    </init-param>
    <init-param>
         <param-name>services</param-name>
         <param-value>com.semika.cometd.ChatService</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>cometd</servlet-name>
    <url-pattern>/cometd/*</url-pattern>
</servlet-mapping>

5.Implementing client side functions.

I think this section should be descriptive. If you allows your users to chat with other users, you need to show the list of online users in you web page, just like Facebook shows the online users inside the right side bar. For that, you can place a simple <span> or <div> tag inside your page. I have done it as follows.
<div id="members"></div>

All the online users will be displayed with in the above container. Once you click on a particular user name, it will open a new chat window similar to Facebook. For each pair of users, it will open a new chat window. To get this behaviour, you should use 'chat.window.js' which I mentioned before. Chatting in between particular pair of users will continue through a dedicated chat window. 

Just after user is logging into your web application as usual way, we should subscribe that user to chat channels. You can do it using the following way. 

 
$(document).ready(function(){ 
    $.cometChat.onLoad({memberListContainerID:'members'});
});

Note that, I have passed the 'id' of online user list container as a configuration parameter. Then, user should be joined with channel as follows.You can call the bellow method with the username.
function join(userName){
   $.cometChat.join(userName);
}

Since for each chat, there is a dedicated chat window just like Facebook, we should maintain global Javascript array to store those created chat window objects. You need to place the following Javascript code inside your page.
function getChatWindowByUserPair(loginUserName, peerUserName) {
    var chatWindow;  
    for(var i = 0; i < chatWindowArray.length; i++) {
       var windowInfo = chatWindowArray[i];
       if (windowInfo.loginUserName == loginUserName && windowInfo.peerUserName == peerUserName) {
           chatWindow =  windowInfo.windowObj;
       }
    }
    return chatWindow;
}
 
function createWindow(loginUserName, peerUserName) {  
    var chatWindow = getChatWindowByUserPair(loginUserName, peerUserName);
    if (chatWindow == null) { //Not chat window created before for this user pair.
       chatWindow = new ChatWindow(); //Create new chat window.
       chatWindow.initWindow({
             loginUserName:loginUserName, 
             peerUserName:peerUserName,
             windowArray:chatWindowArray});
   
       //collect all chat windows opended so far.
       var chatWindowInfo = { peerUserName:peerUserName, 
                              loginUserName:loginUserName,
                              windowObj:chatWindow 
                            };
   
       chatWindowArray.push(chatWindowInfo);
   }
   chatWindow.show();  
   return chatWindow;
}

As I mentioned above, declare following global Javascript variable.
var chatWindowArray = [];   
var config = {
    contextPath: '${pageContext.request.contextPath}'
};

Since I am using a JSP page, I have to get the context path via 'pageContext' variable. If you are using a HTML page, manage it by your self to declare 'config' Javascript global variable.
Now, you almost reached to last part of the tutorial.

5.How does the sample application works?

You can download the comet.war file and deploy it in your server. Point the browser to following URL.

http://localhost:8080/comet

This will bring you to a page which has a text field and button called "Join". Insert some user name as you wish and click on "Join" button. Then you will be forwarded to a another page which has list of online users. Your name is highlighted in red color. To chat in your local machine, You can open another browser (IE and FF) and join to the chat channel. The peer user displays in blue color in the online users list. Once you click on a peer user, it will open a new chat window so that You can chat with him. This functions very similar to Facebook chatting. 

I have tested this chatting application in IE, FF and Crome and works fine. If you want any help of integrating this with your Java base web application, just send me a mail.


You may also like:
Share

Widgets